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