/src/boringssl/crypto/asn1/a_object.cc
Line | Count | Source |
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 | | |
30 | 2.00M | int asn1_marshal_object(CBB *out, const ASN1_OBJECT *in, CBS_ASN1_TAG tag) { |
31 | 2.00M | if (in == nullptr) { |
32 | 0 | OPENSSL_PUT_ERROR(ASN1, ERR_R_PASSED_NULL_PARAMETER); |
33 | 0 | return 0; |
34 | 0 | } |
35 | | |
36 | 2.00M | if (in->length <= 0) { |
37 | 5 | OPENSSL_PUT_ERROR(ASN1, ASN1_R_ILLEGAL_OBJECT); |
38 | 5 | return 0; |
39 | 5 | } |
40 | | |
41 | 2.00M | tag = tag == 0 ? CBS_ASN1_OBJECT : tag; |
42 | 2.00M | return CBB_add_asn1_element(out, tag, in->data, in->length); |
43 | 2.00M | } |
44 | | |
45 | 0 | int i2d_ASN1_OBJECT(const ASN1_OBJECT *in, unsigned char **outp) { |
46 | 0 | return bssl::I2DFromCBB( |
47 | 0 | /*initial_capacity=*/static_cast<size_t>(in->length) + 2, outp, |
48 | 0 | [&](CBB *cbb) -> bool { |
49 | 0 | return asn1_marshal_object(cbb, in, /*tag=*/0); |
50 | 0 | }); |
51 | 0 | } |
52 | | |
53 | 42.3k | int i2t_ASN1_OBJECT(char *buf, int buf_len, const ASN1_OBJECT *a) { |
54 | 42.3k | return OBJ_obj2txt(buf, buf_len, a, 0); |
55 | 42.3k | } |
56 | | |
57 | 31.7k | static int write_str(BIO *bp, const char *str) { |
58 | 31.7k | size_t len = strlen(str); |
59 | 31.7k | if (len > INT_MAX) { |
60 | 0 | OPENSSL_PUT_ERROR(ASN1, ERR_R_OVERFLOW); |
61 | 0 | return -1; |
62 | 0 | } |
63 | 31.7k | return BIO_write(bp, str, (int)len) == (int)len ? (int)len : -1; |
64 | 31.7k | } |
65 | | |
66 | 31.7k | int i2a_ASN1_OBJECT(BIO *bp, const ASN1_OBJECT *a) { |
67 | 31.7k | if (a == nullptr || a->data == nullptr) { |
68 | 0 | return write_str(bp, "NULL"); |
69 | 0 | } |
70 | | |
71 | 31.7k | char buf[80], *allocated = nullptr; |
72 | 31.7k | const char *str = buf; |
73 | 31.7k | int len = i2t_ASN1_OBJECT(buf, sizeof(buf), a); |
74 | 31.7k | if (len > (int)sizeof(buf) - 1) { |
75 | | // The input was truncated. Allocate a buffer that fits. |
76 | 106 | allocated = reinterpret_cast<char *>(OPENSSL_malloc(len + 1)); |
77 | 106 | if (allocated == nullptr) { |
78 | 0 | return -1; |
79 | 0 | } |
80 | 106 | len = i2t_ASN1_OBJECT(allocated, len + 1, a); |
81 | 106 | str = allocated; |
82 | 106 | } |
83 | 31.7k | if (len <= 0) { |
84 | 174 | str = "<INVALID>"; |
85 | 174 | } |
86 | | |
87 | 31.7k | int ret = write_str(bp, str); |
88 | 31.7k | OPENSSL_free(allocated); |
89 | 31.7k | return ret; |
90 | 31.7k | } |
91 | | |
92 | | ASN1_OBJECT *d2i_ASN1_OBJECT(ASN1_OBJECT **out, const unsigned char **inp, |
93 | 0 | long len) { |
94 | 0 | return bssl::D2IFromCBS(out, inp, len, [](CBS *cbs) -> ASN1_OBJECT * { |
95 | 0 | CBS child; |
96 | 0 | if (!CBS_get_asn1(cbs, &child, CBS_ASN1_OBJECT)) { |
97 | 0 | OPENSSL_PUT_ERROR(ASN1, ASN1_R_DECODE_ERROR); |
98 | 0 | return nullptr; |
99 | 0 | } |
100 | 0 | const uint8_t *contents = CBS_data(&child); |
101 | 0 | return c2i_ASN1_OBJECT(nullptr, &contents, CBS_len(&child)); |
102 | 0 | }); |
103 | 0 | } |
104 | | |
105 | | ASN1_OBJECT *c2i_ASN1_OBJECT(ASN1_OBJECT **out, const unsigned char **inp, |
106 | 0 | long len) { |
107 | 0 | return bssl::D2IFromCBS(out, inp, len, [](CBS *cbs) -> ASN1_OBJECT * { |
108 | 0 | if (!CBS_is_valid_asn1_oid(cbs)) { |
109 | 0 | OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_OBJECT_ENCODING); |
110 | 0 | return nullptr; |
111 | 0 | } |
112 | 0 | ASN1_OBJECT *ret = |
113 | 0 | ASN1_OBJECT_create(NID_undef, CBS_data(cbs), CBS_len(cbs), |
114 | 0 | /*sn=*/nullptr, /*ln=*/nullptr); |
115 | 0 | if (ret != nullptr) { |
116 | | // |c2i_ASN1_OBJECT| consumes its whole input on success. |
117 | 0 | BSSL_CHECK(CBS_skip(cbs, CBS_len(cbs))); |
118 | 0 | } |
119 | 0 | return ret; |
120 | 0 | }); |
121 | 0 | } |
122 | | |
123 | 2.07M | ASN1_OBJECT *asn1_parse_object(CBS *cbs, CBS_ASN1_TAG tag) { |
124 | 2.07M | tag = tag == 0 ? CBS_ASN1_OBJECT : tag; |
125 | 2.07M | CBS child; |
126 | 2.07M | if (!CBS_get_asn1(cbs, &child, tag)) { |
127 | 574 | OPENSSL_PUT_ERROR(ASN1, ASN1_R_DECODE_ERROR); |
128 | 574 | return nullptr; |
129 | 574 | } |
130 | 2.07M | if (!CBS_is_valid_asn1_oid(&child)) { |
131 | 398 | OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_OBJECT_ENCODING); |
132 | 398 | return nullptr; |
133 | 398 | } |
134 | 2.07M | return ASN1_OBJECT_create(NID_undef, CBS_data(&child), CBS_len(&child), |
135 | 2.07M | /*sn=*/nullptr, /*ln=*/nullptr); |
136 | 2.07M | } |
137 | | |
138 | 2.08M | ASN1_OBJECT *ASN1_OBJECT_new(void) { |
139 | 2.08M | ASN1_OBJECT *ret; |
140 | | |
141 | 2.08M | ret = (ASN1_OBJECT *)OPENSSL_malloc(sizeof(ASN1_OBJECT)); |
142 | 2.08M | if (ret == nullptr) { |
143 | 0 | return nullptr; |
144 | 0 | } |
145 | 2.08M | ret->length = 0; |
146 | 2.08M | ret->data = nullptr; |
147 | 2.08M | ret->nid = 0; |
148 | 2.08M | ret->sn = nullptr; |
149 | 2.08M | ret->ln = nullptr; |
150 | 2.08M | ret->flags = ASN1_OBJECT_FLAG_DYNAMIC; |
151 | 2.08M | return ret; |
152 | 2.08M | } |
153 | | |
154 | 4.40M | void ASN1_OBJECT_free(ASN1_OBJECT *a) { |
155 | 4.40M | if (a == nullptr) { |
156 | 15.5k | return; |
157 | 15.5k | } |
158 | 4.39M | if (a->flags & ASN1_OBJECT_FLAG_DYNAMIC_STRINGS) { |
159 | 2.08M | OPENSSL_free((void *)a->sn); |
160 | 2.08M | OPENSSL_free((void *)a->ln); |
161 | 2.08M | a->sn = a->ln = nullptr; |
162 | 2.08M | } |
163 | 4.39M | if (a->flags & ASN1_OBJECT_FLAG_DYNAMIC_DATA) { |
164 | 2.08M | OPENSSL_free((void *)a->data); |
165 | 2.08M | a->data = nullptr; |
166 | 2.08M | a->length = 0; |
167 | 2.08M | } |
168 | 4.39M | if (a->flags & ASN1_OBJECT_FLAG_DYNAMIC) { |
169 | 2.08M | OPENSSL_free(a); |
170 | 2.08M | } |
171 | 4.39M | } |
172 | | |
173 | | ASN1_OBJECT *ASN1_OBJECT_create(int nid, const unsigned char *data, size_t len, |
174 | 2.08M | const char *sn, const char *ln) { |
175 | 2.08M | if (len > INT_MAX) { |
176 | 0 | OPENSSL_PUT_ERROR(ASN1, ASN1_R_STRING_TOO_LONG); |
177 | 0 | return nullptr; |
178 | 0 | } |
179 | | |
180 | 2.08M | ASN1_OBJECT o; |
181 | 2.08M | o.sn = sn; |
182 | 2.08M | o.ln = ln; |
183 | 2.08M | o.data = data; |
184 | 2.08M | o.nid = nid; |
185 | 2.08M | o.length = (int)len; |
186 | 2.08M | o.flags = ASN1_OBJECT_FLAG_DYNAMIC | ASN1_OBJECT_FLAG_DYNAMIC_STRINGS | |
187 | 2.08M | ASN1_OBJECT_FLAG_DYNAMIC_DATA; |
188 | 2.08M | return OBJ_dup(&o); |
189 | 2.08M | } |