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