summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjsing <>2022-06-25 15:39:12 +0000
committerjsing <>2022-06-25 15:39:12 +0000
commit3ab5d00cdb582673304e9a788e751bb52462af01 (patch)
tree4c32a379c7481081397694e536925a512b9fe440
parent07a0e24fbcc811580c51bdba7ac4be5b3a8129de (diff)
downloadopenbsd-3ab5d00cdb582673304e9a788e751bb52462af01.tar.gz
openbsd-3ab5d00cdb582673304e9a788e751bb52462af01.tar.bz2
openbsd-3ab5d00cdb582673304e9a788e751bb52462af01.zip
Rewrite ASN1_INTEGER_{get,set}() using CBS/CBB
In the process, prepare to provide ASN1_INTEGER_{get,set}_{u,}int64(). ok beck@ tb@
-rw-r--r--src/lib/libcrypto/asn1/a_int.c237
-rw-r--r--src/lib/libcrypto/asn1/asn1.h13
-rw-r--r--src/lib/libcrypto/asn1/asn1_err.c7
-rw-r--r--src/lib/libcrypto/asn1/asn1_locl.h5
4 files changed, 197 insertions, 65 deletions
diff --git a/src/lib/libcrypto/asn1/a_int.c b/src/lib/libcrypto/asn1/a_int.c
index 6ad0df3d1e..546713ae46 100644
--- a/src/lib/libcrypto/asn1/a_int.c
+++ b/src/lib/libcrypto/asn1/a_int.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: a_int.c,v 1.40 2022/06/25 14:22:54 jsing Exp $ */ 1/* $OpenBSD: a_int.c,v 1.41 2022/06/25 15:39:12 jsing Exp $ */
2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3 * All rights reserved. 3 * All rights reserved.
4 * 4 *
@@ -80,6 +80,16 @@ ASN1_INTEGER_new(void)
80 return (ASN1_INTEGER *)ASN1_item_new(&ASN1_INTEGER_it); 80 return (ASN1_INTEGER *)ASN1_item_new(&ASN1_INTEGER_it);
81} 81}
82 82
83static void
84asn1_aint_clear(ASN1_INTEGER *aint)
85{
86 freezero(aint->data, aint->length);
87
88 memset(aint, 0, sizeof(*aint));
89
90 aint->type = V_ASN1_INTEGER;
91}
92
83void 93void
84ASN1_INTEGER_free(ASN1_INTEGER *a) 94ASN1_INTEGER_free(ASN1_INTEGER *a)
85{ 95{
@@ -117,83 +127,190 @@ ASN1_INTEGER_cmp(const ASN1_INTEGER *a, const ASN1_INTEGER *b)
117} 127}
118 128
119int 129int
120ASN1_INTEGER_set(ASN1_INTEGER *a, long v) 130asn1_aint_get_uint64(CBS *cbs, uint64_t *out_val)
121{ 131{
122 int j, k; 132 uint64_t val = 0;
123 unsigned int i; 133 uint8_t u8;
124 unsigned char buf[sizeof(long) + 1]; 134
125 long d; 135 *out_val = 0;
126 136
127 a->type = V_ASN1_INTEGER; 137 while (CBS_len(cbs) > 0) {
128 /* XXX ssl/ssl_asn1.c:i2d_SSL_SESSION() depends upon this bound vae */ 138 if (!CBS_get_u8(cbs, &u8))
129 if (a->length < (int)(sizeof(long) + 1)) { 139 return 0;
130 free(a->data); 140 if (val > (UINT64_MAX >> 8)) {
131 a->data = calloc(1, sizeof(long) + 1); 141 ASN1error(ASN1_R_TOO_LARGE);
132 } 142 return 0;
133 if (a->data == NULL) { 143 }
134 ASN1error(ERR_R_MALLOC_FAILURE); 144 val = val << 8 | u8;
135 return (0);
136 } 145 }
137 d = v; 146
138 if (d < 0) { 147 *out_val = val;
139 d = -d; 148
140 a->type = V_ASN1_NEG_INTEGER; 149 return 1;
150}
151
152int
153asn1_aint_set_uint64(uint64_t val, uint8_t **out_data, int *out_len)
154{
155 uint8_t *data = NULL;
156 size_t data_len = 0;
157 int started = 0;
158 uint8_t u8;
159 CBB cbb;
160 int i;
161 int ret = 0;
162
163 if (!CBB_init(&cbb, sizeof(long)))
164 goto err;
165
166 if (out_data == NULL || out_len == NULL)
167 goto err;
168 if (*out_data != NULL || *out_len != 0)
169 goto err;
170
171 for (i = sizeof(uint64_t) - 1; i >= 0; i--) {
172 u8 = (val >> (i * 8)) & 0xff;
173 if (!started && i != 0 && u8 == 0)
174 continue;
175 if (!CBB_add_u8(&cbb, u8))
176 goto err;
177 started = 1;
141 } 178 }
142 179
143 for (i = 0; i < sizeof(long); i++) { 180 if (!CBB_finish(&cbb, &data, &data_len))
144 if (d == 0) 181 goto err;
145 break; 182 if (data_len > INT_MAX)
146 buf[i] = (int)d & 0xff; 183 goto err;
147 d >>= 8; 184
185 *out_data = data;
186 *out_len = (int)data_len;
187 data = NULL;
188
189 ret = 1;
190 err:
191 CBB_cleanup(&cbb);
192 freezero(data, data_len);
193
194 return ret;
195}
196
197int
198asn1_aint_get_int64(CBS *cbs, int negative, int64_t *out_val)
199{
200 uint64_t val;
201
202 if (!asn1_aint_get_uint64(cbs, &val))
203 return 0;
204
205 if (negative) {
206 if (val > (uint64_t)INT64_MIN) {
207 ASN1error(ASN1_R_TOO_SMALL);
208 return 0;
209 }
210 *out_val = -(int64_t)val;
211 } else {
212 if (val > (uint64_t)INT64_MAX) {
213 ASN1error(ASN1_R_TOO_LARGE);
214 return 0;
215 }
216 *out_val = (int64_t)val;
148 } 217 }
149 j = 0; 218
150 for (k = i - 1; k >= 0; k--) 219 return 1;
151 a->data[j++] = buf[k];
152 a->length = j;
153 return (1);
154} 220}
155 221
156/* 222int
157 * XXX this particular API is a gibbering eidrich horror that makes it 223ASN1_INTEGER_get_uint64(uint64_t *out_val, const ASN1_INTEGER *aint)
158 * impossible to determine valid return cases from errors.. "a bit
159 * ugly" is preserved for posterity, unfortunately this is probably
160 * unfixable without changing public API
161 */
162long
163ASN1_INTEGER_get(const ASN1_INTEGER *a)
164{ 224{
165 int neg = 0, i; 225 uint64_t val;
166 unsigned long r = 0; 226 CBS cbs;
167 227
168 if (a == NULL) 228 *out_val = 0;
169 return (0L);
170 i = a->type;
171 if (i == V_ASN1_NEG_INTEGER)
172 neg = 1;
173 else if (i != V_ASN1_INTEGER)
174 return -1;
175 229
176 if (!ASN1_INTEGER_valid(a)) 230 if (aint == NULL || aint->length < 0)
177 return -1; /* XXX best effort */ 231 return 0;
178 232
179 if (a->length > (int)sizeof(long)) { 233 if (aint->type == V_ASN1_NEG_INTEGER) {
180 /* hmm... a bit ugly, return all ones */ 234 ASN1error(ASN1_R_ILLEGAL_NEGATIVE_VALUE);
181 return -1; 235 return 0;
182 } 236 }
183 if (a->data == NULL) 237 if (aint->type != V_ASN1_INTEGER) {
238 ASN1error(ASN1_R_WRONG_INTEGER_TYPE);
184 return 0; 239 return 0;
240 }
241
242 CBS_init(&cbs, aint->data, aint->length);
243
244 if (!asn1_aint_get_uint64(&cbs, &val))
245 return 0;
246
247 *out_val = val;
248
249 return 1;
250}
251
252int
253ASN1_INTEGER_set_uint64(ASN1_INTEGER *aint, uint64_t val)
254{
255 asn1_aint_clear(aint);
185 256
186 for (i = 0; i < a->length; i++) { 257 return asn1_aint_set_uint64(val, &aint->data, &aint->length);
187 r <<= 8; 258}
188 r |= (unsigned char)a->data[i]; 259
260int
261ASN1_INTEGER_get_int64(int64_t *out_val, const ASN1_INTEGER *aint)
262{
263 CBS cbs;
264
265 *out_val = 0;
266
267 if (aint == NULL || aint->length < 0)
268 return 0;
269
270 if (aint->type != V_ASN1_INTEGER &&
271 aint->type != V_ASN1_NEG_INTEGER) {
272 ASN1error(ASN1_R_WRONG_INTEGER_TYPE);
273 return 0;
189 } 274 }
190 275
191 if (r > LONG_MAX) 276 CBS_init(&cbs, aint->data, aint->length);
277
278 return asn1_aint_get_int64(&cbs, (aint->type == V_ASN1_NEG_INTEGER),
279 out_val);
280}
281
282int
283ASN1_INTEGER_set_int64(ASN1_INTEGER *aint, int64_t val)
284{
285 asn1_aint_clear(aint);
286
287 if (val < 0) {
288 aint->type = V_ASN1_NEG_INTEGER;
289 val = -val;
290 }
291
292 return asn1_aint_set_uint64((uint64_t)val, &aint->data, &aint->length);
293}
294
295long
296ASN1_INTEGER_get(const ASN1_INTEGER *aint)
297{
298 int64_t val;
299
300 if (!ASN1_INTEGER_get_int64(&val, aint))
192 return -1; 301 return -1;
302 if (val < LONG_MIN || val > LONG_MAX) {
303 /* hmm... a bit ugly, return all ones */
304 return -1;
305 }
306
307 return (long)val;
308}
193 309
194 if (neg) 310int
195 return -(long)r; 311ASN1_INTEGER_set(ASN1_INTEGER *aint, long val)
196 return (long)r; 312{
313 return ASN1_INTEGER_set_int64(aint, val);
197} 314}
198 315
199ASN1_INTEGER * 316ASN1_INTEGER *
diff --git a/src/lib/libcrypto/asn1/asn1.h b/src/lib/libcrypto/asn1/asn1.h
index e569e875c2..d6adb0d22e 100644
--- a/src/lib/libcrypto/asn1/asn1.h
+++ b/src/lib/libcrypto/asn1/asn1.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: asn1.h,v 1.62 2022/01/14 08:53:53 tb Exp $ */ 1/* $OpenBSD: asn1.h,v 1.63 2022/06/25 15:39:12 jsing Exp $ */
2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3 * All rights reserved. 3 * All rights reserved.
4 * 4 *
@@ -748,6 +748,12 @@ int a2d_ASN1_OBJECT(unsigned char *out, int olen, const char *buf, int num);
748ASN1_OBJECT *ASN1_OBJECT_create(int nid, unsigned char *data, int len, 748ASN1_OBJECT *ASN1_OBJECT_create(int nid, unsigned char *data, int len,
749 const char *sn, const char *ln); 749 const char *sn, const char *ln);
750 750
751#ifdef LIBRESSL_INTERNAL
752int ASN1_INTEGER_get_uint64(uint64_t *out_val, const ASN1_INTEGER *aint);
753int ASN1_INTEGER_set_uint64(ASN1_INTEGER *aint, uint64_t val);
754int ASN1_INTEGER_get_int64(int64_t *out_val, const ASN1_INTEGER *aint);
755int ASN1_INTEGER_set_int64(ASN1_INTEGER *aint, int64_t val);
756#endif
751int ASN1_INTEGER_set(ASN1_INTEGER *a, long v); 757int ASN1_INTEGER_set(ASN1_INTEGER *a, long v);
752long ASN1_INTEGER_get(const ASN1_INTEGER *a); 758long ASN1_INTEGER_get(const ASN1_INTEGER *a);
753ASN1_INTEGER *BN_to_ASN1_INTEGER(const BIGNUM *bn, ASN1_INTEGER *ai); 759ASN1_INTEGER *BN_to_ASN1_INTEGER(const BIGNUM *bn, ASN1_INTEGER *ai);
@@ -1109,6 +1115,7 @@ void ERR_load_ASN1_strings(void);
1109#define ASN1_R_ILLEGAL_HEX 178 1115#define ASN1_R_ILLEGAL_HEX 178
1110#define ASN1_R_ILLEGAL_IMPLICIT_TAG 179 1116#define ASN1_R_ILLEGAL_IMPLICIT_TAG 179
1111#define ASN1_R_ILLEGAL_INTEGER 180 1117#define ASN1_R_ILLEGAL_INTEGER 180
1118#define ASN1_R_ILLEGAL_NEGATIVE_VALUE 226
1112#define ASN1_R_ILLEGAL_NESTED_TAGGING 181 1119#define ASN1_R_ILLEGAL_NESTED_TAGGING 181
1113#define ASN1_R_ILLEGAL_NULL 125 1120#define ASN1_R_ILLEGAL_NULL 125
1114#define ASN1_R_ILLEGAL_NULL_VALUE 182 1121#define ASN1_R_ILLEGAL_NULL_VALUE 182
@@ -1168,7 +1175,9 @@ void ERR_load_ASN1_strings(void);
1168#define ASN1_R_TAG_VALUE_TOO_HIGH 153 1175#define ASN1_R_TAG_VALUE_TOO_HIGH 153
1169#define ASN1_R_THE_ASN1_OBJECT_IDENTIFIER_IS_NOT_KNOWN_FOR_THIS_MD 154 1176#define ASN1_R_THE_ASN1_OBJECT_IDENTIFIER_IS_NOT_KNOWN_FOR_THIS_MD 154
1170#define ASN1_R_TIME_NOT_ASCII_FORMAT 193 1177#define ASN1_R_TIME_NOT_ASCII_FORMAT 193
1178#define ASN1_R_TOO_LARGE 223
1171#define ASN1_R_TOO_LONG 155 1179#define ASN1_R_TOO_LONG 155
1180#define ASN1_R_TOO_SMALL 224
1172#define ASN1_R_TYPE_NOT_CONSTRUCTED 156 1181#define ASN1_R_TYPE_NOT_CONSTRUCTED 156
1173#define ASN1_R_UNABLE_TO_DECODE_RSA_KEY 157 1182#define ASN1_R_UNABLE_TO_DECODE_RSA_KEY 157
1174#define ASN1_R_UNABLE_TO_DECODE_RSA_PRIVATE_KEY 158 1183#define ASN1_R_UNABLE_TO_DECODE_RSA_PRIVATE_KEY 158
@@ -1186,11 +1195,11 @@ void ERR_load_ASN1_strings(void);
1186#define ASN1_R_UNSUPPORTED_ENCRYPTION_ALGORITHM 166 1195#define ASN1_R_UNSUPPORTED_ENCRYPTION_ALGORITHM 166
1187#define ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE 167 1196#define ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE 167
1188#define ASN1_R_UNSUPPORTED_TYPE 196 1197#define ASN1_R_UNSUPPORTED_TYPE 196
1198#define ASN1_R_WRONG_INTEGER_TYPE 225
1189#define ASN1_R_WRONG_PUBLIC_KEY_TYPE 200 1199#define ASN1_R_WRONG_PUBLIC_KEY_TYPE 200
1190#define ASN1_R_WRONG_TAG 168 1200#define ASN1_R_WRONG_TAG 168
1191#define ASN1_R_WRONG_TYPE 169 1201#define ASN1_R_WRONG_TYPE 169
1192 1202
1193
1194int ASN1_time_parse(const char *_bytes, size_t _len, struct tm *_tm, int _mode); 1203int ASN1_time_parse(const char *_bytes, size_t _len, struct tm *_tm, int _mode);
1195int ASN1_time_tm_cmp(struct tm *_tm1, struct tm *_tm2); 1204int ASN1_time_tm_cmp(struct tm *_tm1, struct tm *_tm2);
1196#ifdef __cplusplus 1205#ifdef __cplusplus
diff --git a/src/lib/libcrypto/asn1/asn1_err.c b/src/lib/libcrypto/asn1/asn1_err.c
index e2c56deb5b..98db4f7802 100644
--- a/src/lib/libcrypto/asn1/asn1_err.c
+++ b/src/lib/libcrypto/asn1/asn1_err.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: asn1_err.c,v 1.22 2020/12/08 15:06:42 tb Exp $ */ 1/* $OpenBSD: asn1_err.c,v 1.23 2022/06/25 15:39:12 jsing Exp $ */
2/* ==================================================================== 2/* ====================================================================
3 * Copyright (c) 1999-2011 The OpenSSL Project. All rights reserved. 3 * Copyright (c) 1999-2011 The OpenSSL Project. All rights reserved.
4 * 4 *
@@ -118,6 +118,7 @@ static ERR_STRING_DATA ASN1_str_reasons[] = {
118 {ERR_REASON(ASN1_R_ILLEGAL_HEX) , "illegal hex"}, 118 {ERR_REASON(ASN1_R_ILLEGAL_HEX) , "illegal hex"},
119 {ERR_REASON(ASN1_R_ILLEGAL_IMPLICIT_TAG) , "illegal implicit tag"}, 119 {ERR_REASON(ASN1_R_ILLEGAL_IMPLICIT_TAG) , "illegal implicit tag"},
120 {ERR_REASON(ASN1_R_ILLEGAL_INTEGER) , "illegal integer"}, 120 {ERR_REASON(ASN1_R_ILLEGAL_INTEGER) , "illegal integer"},
121 {ERR_REASON(ASN1_R_ILLEGAL_NEGATIVE_VALUE), "illegal negative value"},
121 {ERR_REASON(ASN1_R_ILLEGAL_NESTED_TAGGING), "illegal nested tagging"}, 122 {ERR_REASON(ASN1_R_ILLEGAL_NESTED_TAGGING), "illegal nested tagging"},
122 {ERR_REASON(ASN1_R_ILLEGAL_NULL) , "illegal null"}, 123 {ERR_REASON(ASN1_R_ILLEGAL_NULL) , "illegal null"},
123 {ERR_REASON(ASN1_R_ILLEGAL_NULL_VALUE) , "illegal null value"}, 124 {ERR_REASON(ASN1_R_ILLEGAL_NULL_VALUE) , "illegal null value"},
@@ -177,7 +178,9 @@ static ERR_STRING_DATA ASN1_str_reasons[] = {
177 {ERR_REASON(ASN1_R_TAG_VALUE_TOO_HIGH) , "tag value too high"}, 178 {ERR_REASON(ASN1_R_TAG_VALUE_TOO_HIGH) , "tag value too high"},
178 {ERR_REASON(ASN1_R_THE_ASN1_OBJECT_IDENTIFIER_IS_NOT_KNOWN_FOR_THIS_MD), "the asn1 object identifier is not known for this md"}, 179 {ERR_REASON(ASN1_R_THE_ASN1_OBJECT_IDENTIFIER_IS_NOT_KNOWN_FOR_THIS_MD), "the asn1 object identifier is not known for this md"},
179 {ERR_REASON(ASN1_R_TIME_NOT_ASCII_FORMAT), "time not ascii format"}, 180 {ERR_REASON(ASN1_R_TIME_NOT_ASCII_FORMAT), "time not ascii format"},
181 {ERR_REASON(ASN1_R_TOO_LARGE) , "too large"},
180 {ERR_REASON(ASN1_R_TOO_LONG) , "too long"}, 182 {ERR_REASON(ASN1_R_TOO_LONG) , "too long"},
183 {ERR_REASON(ASN1_R_TOO_SMALL) , "too small"},
181 {ERR_REASON(ASN1_R_TYPE_NOT_CONSTRUCTED) , "type not constructed"}, 184 {ERR_REASON(ASN1_R_TYPE_NOT_CONSTRUCTED) , "type not constructed"},
182 {ERR_REASON(ASN1_R_UNABLE_TO_DECODE_RSA_KEY), "unable to decode rsa key"}, 185 {ERR_REASON(ASN1_R_UNABLE_TO_DECODE_RSA_KEY), "unable to decode rsa key"},
183 {ERR_REASON(ASN1_R_UNABLE_TO_DECODE_RSA_PRIVATE_KEY), "unable to decode rsa private key"}, 186 {ERR_REASON(ASN1_R_UNABLE_TO_DECODE_RSA_PRIVATE_KEY), "unable to decode rsa private key"},
@@ -195,12 +198,12 @@ static ERR_STRING_DATA ASN1_str_reasons[] = {
195 {ERR_REASON(ASN1_R_UNSUPPORTED_ENCRYPTION_ALGORITHM), "unsupported encryption algorithm"}, 198 {ERR_REASON(ASN1_R_UNSUPPORTED_ENCRYPTION_ALGORITHM), "unsupported encryption algorithm"},
196 {ERR_REASON(ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE), "unsupported public key type"}, 199 {ERR_REASON(ASN1_R_UNSUPPORTED_PUBLIC_KEY_TYPE), "unsupported public key type"},
197 {ERR_REASON(ASN1_R_UNSUPPORTED_TYPE) , "unsupported type"}, 200 {ERR_REASON(ASN1_R_UNSUPPORTED_TYPE) , "unsupported type"},
201 {ERR_REASON(ASN1_R_WRONG_INTEGER_TYPE) , "wrong integer type"},
198 {ERR_REASON(ASN1_R_WRONG_PUBLIC_KEY_TYPE), "wrong public key type"}, 202 {ERR_REASON(ASN1_R_WRONG_PUBLIC_KEY_TYPE), "wrong public key type"},
199 {ERR_REASON(ASN1_R_WRONG_TAG) , "wrong tag"}, 203 {ERR_REASON(ASN1_R_WRONG_TAG) , "wrong tag"},
200 {ERR_REASON(ASN1_R_WRONG_TYPE) , "wrong type"}, 204 {ERR_REASON(ASN1_R_WRONG_TYPE) , "wrong type"},
201 {0, NULL} 205 {0, NULL}
202}; 206};
203
204#endif 207#endif
205 208
206void 209void
diff --git a/src/lib/libcrypto/asn1/asn1_locl.h b/src/lib/libcrypto/asn1/asn1_locl.h
index db456c8ff2..2d007061f2 100644
--- a/src/lib/libcrypto/asn1/asn1_locl.h
+++ b/src/lib/libcrypto/asn1/asn1_locl.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: asn1_locl.h,v 1.32 2022/05/17 09:17:20 tb Exp $ */ 1/* $OpenBSD: asn1_locl.h,v 1.33 2022/06/25 15:39:12 jsing Exp $ */
2/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL 2/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
3 * project 2006. 3 * project 2006.
4 */ 4 */
@@ -208,6 +208,9 @@ int asn1_tag2charwidth(int tag);
208int asn1_abs_set_unused_bits(ASN1_BIT_STRING *abs, uint8_t unused_bits); 208int asn1_abs_set_unused_bits(ASN1_BIT_STRING *abs, uint8_t unused_bits);
209int c2i_ASN1_BIT_STRING_cbs(ASN1_BIT_STRING **out_abs, CBS *cbs); 209int c2i_ASN1_BIT_STRING_cbs(ASN1_BIT_STRING **out_abs, CBS *cbs);
210 210
211int asn1_aint_get_uint64(CBS *cbs, uint64_t *out_val);
212int asn1_aint_set_uint64(uint64_t val, uint8_t **out_data, int *out_len);
213int asn1_aint_get_int64(CBS *cbs, int negative, int64_t *out_val);
211int c2i_ASN1_INTEGER_cbs(ASN1_INTEGER **out_aint, CBS *cbs); 214int c2i_ASN1_INTEGER_cbs(ASN1_INTEGER **out_aint, CBS *cbs);
212 215
213int c2i_ASN1_OBJECT_cbs(ASN1_OBJECT **out_aobj, CBS *content); 216int c2i_ASN1_OBJECT_cbs(ASN1_OBJECT **out_aobj, CBS *content);