diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/lib/libcrypto/asn1/a_object.c | 288 |
1 files changed, 167 insertions, 121 deletions
diff --git a/src/lib/libcrypto/asn1/a_object.c b/src/lib/libcrypto/asn1/a_object.c index 120437bf10..0061ccb880 100644 --- a/src/lib/libcrypto/asn1/a_object.c +++ b/src/lib/libcrypto/asn1/a_object.c | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* $OpenBSD: a_object.c,v 1.41 2022/03/15 18:47:22 jsing Exp $ */ | 1 | /* $OpenBSD: a_object.c,v 1.42 2022/03/19 17:35:52 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 | * |
| @@ -62,7 +62,6 @@ | |||
| 62 | 62 | ||
| 63 | #include <openssl/asn1.h> | 63 | #include <openssl/asn1.h> |
| 64 | #include <openssl/asn1t.h> | 64 | #include <openssl/asn1t.h> |
| 65 | #include <openssl/bn.h> | ||
| 66 | #include <openssl/err.h> | 65 | #include <openssl/err.h> |
| 67 | #include <openssl/buffer.h> | 66 | #include <openssl/buffer.h> |
| 68 | #include <openssl/objects.h> | 67 | #include <openssl/objects.h> |
| @@ -146,128 +145,25 @@ i2d_ASN1_OBJECT(const ASN1_OBJECT *a, unsigned char **pp) | |||
| 146 | return (objsize); | 145 | return (objsize); |
| 147 | } | 146 | } |
| 148 | 147 | ||
| 149 | int | 148 | static int |
| 150 | a2d_ASN1_OBJECT(unsigned char *out, int olen, const char *buf, int num) | 149 | oid_add_arc(CBB *cbb, uint64_t arc) |
| 151 | { | 150 | { |
| 152 | int i, first, len = 0, c, use_bn; | 151 | int started = 0; |
| 153 | char ftmp[24], *tmp = ftmp; | 152 | uint8_t val; |
| 154 | int tmpsize = sizeof ftmp; | 153 | int i; |
| 155 | const char *p; | 154 | |
| 156 | unsigned long l; | 155 | for (i = (sizeof(arc) * 8) / 7; i >= 0; i--) { |
| 157 | BIGNUM *bl = NULL; | 156 | val = (arc >> (i * 7)) & 0x7f; |
| 158 | 157 | if (!started && i != 0 && val == 0) | |
| 159 | if (num == 0) | 158 | continue; |
| 160 | return (0); | 159 | if (i > 0) |
| 161 | else if (num == -1) | 160 | val |= 0x80; |
| 162 | num = strlen(buf); | 161 | if (!CBB_add_u8(cbb, val)) |
| 163 | 162 | return 0; | |
| 164 | p = buf; | 163 | started = 1; |
| 165 | c = *(p++); | ||
| 166 | num--; | ||
| 167 | if ((c >= '0') && (c <= '2')) { | ||
| 168 | first= c-'0'; | ||
| 169 | } else { | ||
| 170 | ASN1error(ASN1_R_FIRST_NUM_TOO_LARGE); | ||
| 171 | goto err; | ||
| 172 | } | ||
| 173 | |||
| 174 | if (num <= 0) { | ||
| 175 | ASN1error(ASN1_R_MISSING_SECOND_NUMBER); | ||
| 176 | goto err; | ||
| 177 | } | ||
| 178 | c = *(p++); | ||
| 179 | num--; | ||
| 180 | for (;;) { | ||
| 181 | if (num <= 0) | ||
| 182 | break; | ||
| 183 | if ((c != '.') && (c != ' ')) { | ||
| 184 | ASN1error(ASN1_R_INVALID_SEPARATOR); | ||
| 185 | goto err; | ||
| 186 | } | ||
| 187 | l = 0; | ||
| 188 | use_bn = 0; | ||
| 189 | for (;;) { | ||
| 190 | if (num <= 0) | ||
| 191 | break; | ||
| 192 | num--; | ||
| 193 | c = *(p++); | ||
| 194 | if ((c == ' ') || (c == '.')) | ||
| 195 | break; | ||
| 196 | if ((c < '0') || (c > '9')) { | ||
| 197 | ASN1error(ASN1_R_INVALID_DIGIT); | ||
| 198 | goto err; | ||
| 199 | } | ||
| 200 | if (!use_bn && l >= ((ULONG_MAX - 80) / 10L)) { | ||
| 201 | use_bn = 1; | ||
| 202 | if (!bl) | ||
| 203 | bl = BN_new(); | ||
| 204 | if (!bl || !BN_set_word(bl, l)) | ||
| 205 | goto err; | ||
| 206 | } | ||
| 207 | if (use_bn) { | ||
| 208 | if (!BN_mul_word(bl, 10L) || | ||
| 209 | !BN_add_word(bl, c-'0')) | ||
| 210 | goto err; | ||
| 211 | } else | ||
| 212 | l = l * 10L + (long)(c - '0'); | ||
| 213 | } | ||
| 214 | if (len == 0) { | ||
| 215 | if ((first < 2) && (l >= 40)) { | ||
| 216 | ASN1error(ASN1_R_SECOND_NUMBER_TOO_LARGE); | ||
| 217 | goto err; | ||
| 218 | } | ||
| 219 | if (use_bn) { | ||
| 220 | if (!BN_add_word(bl, first * 40)) | ||
| 221 | goto err; | ||
| 222 | } else | ||
| 223 | l += (long)first * 40; | ||
| 224 | } | ||
| 225 | i = 0; | ||
| 226 | if (use_bn) { | ||
| 227 | int blsize; | ||
| 228 | blsize = BN_num_bits(bl); | ||
| 229 | blsize = (blsize + 6) / 7; | ||
| 230 | if (blsize > tmpsize) { | ||
| 231 | if (tmp != ftmp) | ||
| 232 | free(tmp); | ||
| 233 | tmpsize = blsize + 32; | ||
| 234 | tmp = malloc(tmpsize); | ||
| 235 | if (!tmp) | ||
| 236 | goto err; | ||
| 237 | } | ||
| 238 | while (blsize--) | ||
| 239 | tmp[i++] = (unsigned char)BN_div_word(bl, 0x80L); | ||
| 240 | } else { | ||
| 241 | |||
| 242 | for (;;) { | ||
| 243 | tmp[i++] = (unsigned char)l & 0x7f; | ||
| 244 | l >>= 7L; | ||
| 245 | if (l == 0L) | ||
| 246 | break; | ||
| 247 | } | ||
| 248 | |||
| 249 | } | ||
| 250 | if (out != NULL) { | ||
| 251 | if (len + i > olen) { | ||
| 252 | ASN1error(ASN1_R_BUFFER_TOO_SMALL); | ||
| 253 | goto err; | ||
| 254 | } | ||
| 255 | while (--i > 0) | ||
| 256 | out[len++] = tmp[i]|0x80; | ||
| 257 | out[len++] = tmp[0]; | ||
| 258 | } else | ||
| 259 | len += i; | ||
| 260 | } | 164 | } |
| 261 | if (tmp != ftmp) | ||
| 262 | free(tmp); | ||
| 263 | BN_free(bl); | ||
| 264 | return (len); | ||
| 265 | 165 | ||
| 266 | err: | 166 | return 1; |
| 267 | if (tmp != ftmp) | ||
| 268 | free(tmp); | ||
| 269 | BN_free(bl); | ||
| 270 | return (0); | ||
| 271 | } | 167 | } |
| 272 | 168 | ||
| 273 | static int | 169 | static int |
| @@ -310,6 +206,111 @@ oid_add_arc_txt(CBB *cbb, uint64_t arc, int first) | |||
| 310 | } | 206 | } |
| 311 | 207 | ||
| 312 | static int | 208 | static int |
| 209 | oid_parse_arc_txt(CBS *cbs, uint64_t *out_arc, char *separator, int first) | ||
| 210 | { | ||
| 211 | uint64_t arc = 0; | ||
| 212 | int digits = 0; | ||
| 213 | uint8_t val; | ||
| 214 | |||
| 215 | if (!first) { | ||
| 216 | if (!CBS_get_u8(cbs, &val)) | ||
| 217 | return 0; | ||
| 218 | if ((*separator == 0 && val != '.' && val != ' ') || | ||
| 219 | (*separator != 0 && val != *separator)) { | ||
| 220 | ASN1error(ASN1_R_INVALID_SEPARATOR); | ||
| 221 | return 0; | ||
| 222 | } | ||
| 223 | *separator = val; | ||
| 224 | } | ||
| 225 | |||
| 226 | while (CBS_len(cbs) > 0) { | ||
| 227 | if (!CBS_peek_u8(cbs, &val)) | ||
| 228 | return 0; | ||
| 229 | if (val == '.' || val == ' ') | ||
| 230 | break; | ||
| 231 | |||
| 232 | if (!CBS_get_u8(cbs, &val)) | ||
| 233 | return 0; | ||
| 234 | if (val < '0' || val > '9') { | ||
| 235 | /* For the first arc we treat this as the separator. */ | ||
| 236 | if (first) { | ||
| 237 | ASN1error(ASN1_R_INVALID_SEPARATOR); | ||
| 238 | return 0; | ||
| 239 | } | ||
| 240 | ASN1error(ASN1_R_INVALID_DIGIT); | ||
| 241 | return 0; | ||
| 242 | } | ||
| 243 | val -= '0'; | ||
| 244 | |||
| 245 | if (digits > 0 && arc == 0 && val == 0) { | ||
| 246 | ASN1error(ASN1_R_INVALID_NUMBER); | ||
| 247 | return 0; | ||
| 248 | } | ||
| 249 | digits++; | ||
| 250 | |||
| 251 | if (arc > UINT64_MAX / 10) { | ||
| 252 | ASN1error(ASN1_R_TOO_LONG); | ||
| 253 | return 0; | ||
| 254 | } | ||
| 255 | arc = arc * 10 + val; | ||
| 256 | } | ||
| 257 | |||
| 258 | if (digits < 1) { | ||
| 259 | ASN1error(ASN1_R_INVALID_NUMBER); | ||
| 260 | return 0; | ||
| 261 | } | ||
| 262 | |||
| 263 | *out_arc = arc; | ||
| 264 | |||
| 265 | return 1; | ||
| 266 | } | ||
| 267 | |||
| 268 | static int | ||
| 269 | a2c_ASN1_OBJECT_internal(CBB *cbb, CBS *cbs) | ||
| 270 | { | ||
| 271 | uint64_t arc, si1, si2; | ||
| 272 | char separator = 0; | ||
| 273 | |||
| 274 | if (!oid_parse_arc_txt(cbs, &si1, &separator, 1)) | ||
| 275 | return 0; | ||
| 276 | |||
| 277 | if (CBS_len(cbs) == 0) { | ||
| 278 | ASN1error(ASN1_R_MISSING_SECOND_NUMBER); | ||
| 279 | return 0; | ||
| 280 | } | ||
| 281 | |||
| 282 | if (!oid_parse_arc_txt(cbs, &si2, &separator, 0)) | ||
| 283 | return 0; | ||
| 284 | |||
| 285 | /* | ||
| 286 | * X.690 section 8.19 - the first two subidentifiers are encoded as | ||
| 287 | * (x * 40) + y, with x being limited to [0,1,2]. The second | ||
| 288 | * subidentifier cannot exceed 39 for x < 2. | ||
| 289 | */ | ||
| 290 | if (si1 > 2) { | ||
| 291 | ASN1error(ASN1_R_FIRST_NUM_TOO_LARGE); | ||
| 292 | return 0; | ||
| 293 | } | ||
| 294 | if ((si1 < 2 && si2 >= 40) || si2 > UINT64_MAX - si1 * 40) { | ||
| 295 | ASN1error(ASN1_R_SECOND_NUMBER_TOO_LARGE); | ||
| 296 | return 0; | ||
| 297 | } | ||
| 298 | arc = si1 * 40 + si2; | ||
| 299 | |||
| 300 | if (!oid_add_arc(cbb, arc)) | ||
| 301 | return 0; | ||
| 302 | |||
| 303 | while (CBS_len(cbs) > 0) { | ||
| 304 | if (!oid_parse_arc_txt(cbs, &arc, &separator, 0)) | ||
| 305 | return 0; | ||
| 306 | if (!oid_add_arc(cbb, arc)) | ||
| 307 | return 0; | ||
| 308 | } | ||
| 309 | |||
| 310 | return 1; | ||
| 311 | } | ||
| 312 | |||
| 313 | static int | ||
| 313 | c2a_ASN1_OBJECT(CBS *cbs, CBB *cbb) | 314 | c2a_ASN1_OBJECT(CBS *cbs, CBB *cbb) |
| 314 | { | 315 | { |
| 315 | uint64_t arc, si1, si2; | 316 | uint64_t arc, si1, si2; |
| @@ -343,6 +344,51 @@ c2a_ASN1_OBJECT(CBS *cbs, CBB *cbb) | |||
| 343 | return 1; | 344 | return 1; |
| 344 | } | 345 | } |
| 345 | 346 | ||
| 347 | int | ||
| 348 | a2d_ASN1_OBJECT(unsigned char *out, int out_len, const char *in, int in_len) | ||
| 349 | { | ||
| 350 | uint8_t *data = NULL; | ||
| 351 | size_t data_len; | ||
| 352 | CBS cbs; | ||
| 353 | CBB cbb; | ||
| 354 | int ret = 0; | ||
| 355 | |||
| 356 | memset(&cbb, 0, sizeof(cbb)); | ||
| 357 | |||
| 358 | if (in_len == -1) | ||
| 359 | in_len = strlen(in); | ||
| 360 | if (in_len <= 0) | ||
| 361 | goto err; | ||
| 362 | |||
| 363 | CBS_init(&cbs, in, in_len); | ||
| 364 | |||
| 365 | if (!CBB_init(&cbb, 0)) | ||
| 366 | goto err; | ||
| 367 | if (!a2c_ASN1_OBJECT_internal(&cbb, &cbs)) | ||
| 368 | goto err; | ||
| 369 | if (!CBB_finish(&cbb, &data, &data_len)) | ||
| 370 | goto err; | ||
| 371 | |||
| 372 | if (data_len > INT_MAX) | ||
| 373 | goto err; | ||
| 374 | |||
| 375 | if (out != NULL) { | ||
| 376 | if (out_len <= 0 || (size_t)out_len < data_len) { | ||
| 377 | ASN1error(ASN1_R_BUFFER_TOO_SMALL); | ||
| 378 | goto err; | ||
| 379 | } | ||
| 380 | memcpy(out, data, data_len); | ||
| 381 | } | ||
| 382 | |||
| 383 | ret = (int)data_len; | ||
| 384 | |||
| 385 | err: | ||
| 386 | CBB_cleanup(&cbb); | ||
| 387 | free(data); | ||
| 388 | |||
| 389 | return ret; | ||
| 390 | } | ||
| 391 | |||
| 346 | static int | 392 | static int |
| 347 | i2t_ASN1_OBJECT_oid(const ASN1_OBJECT *aobj, CBB *cbb) | 393 | i2t_ASN1_OBJECT_oid(const ASN1_OBJECT *aobj, CBB *cbb) |
| 348 | { | 394 | { |
