• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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