1 /*
2 * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
3 *
4 * Licensed under the OpenSSL license (the "License"). You may not use
5 * this file except in compliance with the License. You can obtain a copy
6 * in the file LICENSE in the source distribution or at
7 * https://www.openssl.org/source/license.html
8 */
9
10 #include <openssl/asn1.h>
11
12 #include <limits.h>
13 #include <string.h>
14
15 #include <openssl/bytestring.h>
16 #include <openssl/err.h>
17 #include <openssl/mem.h>
18 #include <openssl/obj.h>
19
20 #include "../bytestring/internal.h"
21 #include "../internal.h"
22 #include "internal.h"
23
24
i2d_ASN1_OBJECT(const ASN1_OBJECT * in,unsigned char ** outp)25 int i2d_ASN1_OBJECT(const ASN1_OBJECT *in, unsigned char **outp) {
26 if (in == NULL) {
27 OPENSSL_PUT_ERROR(ASN1, ERR_R_PASSED_NULL_PARAMETER);
28 return -1;
29 }
30
31 if (in->length <= 0) {
32 OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_OBJECT);
33 return -1;
34 }
35
36 CBB cbb, child;
37 if (!CBB_init(&cbb, (size_t)in->length + 2) ||
38 !CBB_add_asn1(&cbb, &child, CBS_ASN1_OBJECT) ||
39 !CBB_add_bytes(&child, in->data, in->length)) {
40 CBB_cleanup(&cbb);
41 return -1;
42 }
43
44 return CBB_finish_i2d(&cbb, outp);
45 }
46
i2t_ASN1_OBJECT(char * buf,int buf_len,const ASN1_OBJECT * a)47 int i2t_ASN1_OBJECT(char *buf, int buf_len, const ASN1_OBJECT *a) {
48 return OBJ_obj2txt(buf, buf_len, a, 0);
49 }
50
write_str(BIO * bp,const char * str)51 static int write_str(BIO *bp, const char *str) {
52 size_t len = strlen(str);
53 if (len > INT_MAX) {
54 OPENSSL_PUT_ERROR(ASN1, ERR_R_OVERFLOW);
55 return -1;
56 }
57 return BIO_write(bp, str, (int)len) == (int)len ? (int)len : -1;
58 }
59
i2a_ASN1_OBJECT(BIO * bp,const ASN1_OBJECT * a)60 int i2a_ASN1_OBJECT(BIO *bp, const ASN1_OBJECT *a) {
61 if (a == NULL || a->data == NULL) {
62 return write_str(bp, "NULL");
63 }
64
65 char buf[80], *allocated = NULL;
66 const char *str = buf;
67 int len = i2t_ASN1_OBJECT(buf, sizeof(buf), a);
68 if (len > (int)sizeof(buf) - 1) {
69 // The input was truncated. Allocate a buffer that fits.
70 allocated = reinterpret_cast<char *>(OPENSSL_malloc(len + 1));
71 if (allocated == NULL) {
72 return -1;
73 }
74 len = i2t_ASN1_OBJECT(allocated, len + 1, a);
75 str = allocated;
76 }
77 if (len <= 0) {
78 str = "<INVALID>";
79 }
80
81 int ret = write_str(bp, str);
82 OPENSSL_free(allocated);
83 return ret;
84 }
85
d2i_ASN1_OBJECT(ASN1_OBJECT ** out,const unsigned char ** inp,long len)86 ASN1_OBJECT *d2i_ASN1_OBJECT(ASN1_OBJECT **out, const unsigned char **inp,
87 long len) {
88 if (len < 0) {
89 return NULL;
90 }
91
92 CBS cbs, child;
93 CBS_init(&cbs, *inp, (size_t)len);
94 if (!CBS_get_asn1(&cbs, &child, CBS_ASN1_OBJECT)) {
95 OPENSSL_PUT_ERROR(ASN1, ASN1_R_DECODE_ERROR);
96 return NULL;
97 }
98
99 const uint8_t *contents = CBS_data(&child);
100 ASN1_OBJECT *ret = c2i_ASN1_OBJECT(out, &contents, CBS_len(&child));
101 if (ret != NULL) {
102 // |c2i_ASN1_OBJECT| should have consumed the entire input.
103 assert(CBS_data(&cbs) == contents);
104 *inp = CBS_data(&cbs);
105 }
106 return ret;
107 }
108
c2i_ASN1_OBJECT(ASN1_OBJECT ** out,const unsigned char ** inp,long len)109 ASN1_OBJECT *c2i_ASN1_OBJECT(ASN1_OBJECT **out, const unsigned char **inp,
110 long len) {
111 if (len < 0) {
112 OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_OBJECT_ENCODING);
113 return NULL;
114 }
115
116 CBS cbs;
117 CBS_init(&cbs, *inp, (size_t)len);
118 if (!CBS_is_valid_asn1_oid(&cbs)) {
119 OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_OBJECT_ENCODING);
120 return NULL;
121 }
122
123 ASN1_OBJECT *ret = ASN1_OBJECT_create(NID_undef, *inp, (size_t)len,
124 /*sn=*/NULL, /*ln=*/NULL);
125 if (ret == NULL) {
126 return NULL;
127 }
128
129 if (out != NULL) {
130 ASN1_OBJECT_free(*out);
131 *out = ret;
132 }
133 *inp += len; // All bytes were consumed.
134 return ret;
135 }
136
ASN1_OBJECT_new(void)137 ASN1_OBJECT *ASN1_OBJECT_new(void) {
138 ASN1_OBJECT *ret;
139
140 ret = (ASN1_OBJECT *)OPENSSL_malloc(sizeof(ASN1_OBJECT));
141 if (ret == NULL) {
142 return NULL;
143 }
144 ret->length = 0;
145 ret->data = NULL;
146 ret->nid = 0;
147 ret->sn = NULL;
148 ret->ln = NULL;
149 ret->flags = ASN1_OBJECT_FLAG_DYNAMIC;
150 return ret;
151 }
152
ASN1_OBJECT_free(ASN1_OBJECT * a)153 void ASN1_OBJECT_free(ASN1_OBJECT *a) {
154 if (a == NULL) {
155 return;
156 }
157 if (a->flags & ASN1_OBJECT_FLAG_DYNAMIC_STRINGS) {
158 OPENSSL_free((void *)a->sn);
159 OPENSSL_free((void *)a->ln);
160 a->sn = a->ln = NULL;
161 }
162 if (a->flags & ASN1_OBJECT_FLAG_DYNAMIC_DATA) {
163 OPENSSL_free((void *)a->data);
164 a->data = NULL;
165 a->length = 0;
166 }
167 if (a->flags & ASN1_OBJECT_FLAG_DYNAMIC) {
168 OPENSSL_free(a);
169 }
170 }
171
ASN1_OBJECT_create(int nid,const unsigned char * data,size_t len,const char * sn,const char * ln)172 ASN1_OBJECT *ASN1_OBJECT_create(int nid, const unsigned char *data, size_t len,
173 const char *sn, const char *ln) {
174 if (len > INT_MAX) {
175 OPENSSL_PUT_ERROR(ASN1, ASN1_R_STRING_TOO_LONG);
176 return NULL;
177 }
178
179 ASN1_OBJECT o;
180 o.sn = sn;
181 o.ln = ln;
182 o.data = data;
183 o.nid = nid;
184 o.length = (int)len;
185 o.flags = ASN1_OBJECT_FLAG_DYNAMIC | ASN1_OBJECT_FLAG_DYNAMIC_STRINGS |
186 ASN1_OBJECT_FLAG_DYNAMIC_DATA;
187 return OBJ_dup(&o);
188 }
189