diff options
Diffstat (limited to '')
| -rw-r--r-- | src/lib/libcrypto/asn1/asn1_item.c | 143 |
1 files changed, 89 insertions, 54 deletions
diff --git a/src/lib/libcrypto/asn1/asn1_item.c b/src/lib/libcrypto/asn1/asn1_item.c index 4458ceb866..87f426c6f8 100644 --- a/src/lib/libcrypto/asn1/asn1_item.c +++ b/src/lib/libcrypto/asn1/asn1_item.c | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* $OpenBSD: asn1_item.c,v 1.16 2023/07/07 19:37:52 beck Exp $ */ | 1 | /* $OpenBSD: asn1_item.c,v 1.17 2023/07/13 20:59:10 tb 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 | * |
| @@ -230,73 +230,59 @@ ASN1_item_sign(const ASN1_ITEM *it, X509_ALGOR *algor1, X509_ALGOR *algor2, | |||
| 230 | return ASN1_item_sign_ctx(it, algor1, algor2, signature, asn, &ctx); | 230 | return ASN1_item_sign_ctx(it, algor1, algor2, signature, asn, &ctx); |
| 231 | } | 231 | } |
| 232 | 232 | ||
| 233 | int | 233 | static int |
| 234 | ASN1_item_sign_ctx(const ASN1_ITEM *it, X509_ALGOR *algor1, X509_ALGOR *algor2, | 234 | asn1_item_set_algorithm_identifiers(EVP_MD_CTX *ctx, X509_ALGOR *algor1, |
| 235 | ASN1_BIT_STRING *signature, void *asn, EVP_MD_CTX *ctx) | 235 | X509_ALGOR *algor2) |
| 236 | { | 236 | { |
| 237 | const EVP_MD *type; | ||
| 238 | EVP_PKEY *pkey; | 237 | EVP_PKEY *pkey; |
| 239 | unsigned char *in = NULL, *out = NULL; | 238 | ASN1_OBJECT *aobj; |
| 240 | size_t out_len = 0; | 239 | const EVP_MD *md; |
| 241 | int in_len = 0; | 240 | int sign_id, sign_param; |
| 242 | int signid, paramtype; | ||
| 243 | int rv = 2; | ||
| 244 | int ret = 0; | ||
| 245 | 241 | ||
| 246 | if ((pkey = EVP_PKEY_CTX_get0_pkey(ctx->pctx)) == NULL) { | 242 | if ((pkey = EVP_PKEY_CTX_get0_pkey(ctx->pctx)) == NULL) { |
| 247 | ASN1error(ASN1_R_CONTEXT_NOT_INITIALISED); | 243 | ASN1error(ASN1_R_CONTEXT_NOT_INITIALISED); |
| 248 | return 0; | 244 | return 0; |
| 249 | } | 245 | } |
| 250 | 246 | ||
| 251 | if (pkey->ameth == NULL) { | 247 | if ((md = EVP_MD_CTX_md(ctx)) == NULL) { |
| 252 | ASN1error(ASN1_R_DIGEST_AND_KEY_TYPE_NOT_SUPPORTED); | 248 | ASN1error(ASN1_R_CONTEXT_NOT_INITIALISED); |
| 253 | return 0; | 249 | return 0; |
| 254 | } | 250 | } |
| 255 | 251 | ||
| 256 | if (pkey->ameth->item_sign != NULL) { | 252 | if (!OBJ_find_sigid_by_algs(&sign_id, EVP_MD_nid(md), |
| 257 | rv = pkey->ameth->item_sign(ctx, it, asn, algor1, algor2, | 253 | pkey->ameth->pkey_id)) { |
| 258 | signature); | 254 | ASN1error(ASN1_R_DIGEST_AND_KEY_TYPE_NOT_SUPPORTED); |
| 259 | if (rv == 1) { | 255 | return 0; |
| 260 | out_len = signature->length; | 256 | } |
| 261 | goto done; | 257 | if ((aobj = OBJ_nid2obj(sign_id)) == NULL) { |
| 262 | } | 258 | ASN1error(ASN1_R_UNKNOWN_OBJECT_TYPE); |
| 263 | /* Return value meanings: | 259 | return 0; |
| 264 | * <=0: error. | ||
| 265 | * 1: method does everything. | ||
| 266 | * 2: carry on as normal. | ||
| 267 | * 3: ASN1 method sets algorithm identifiers: just sign. | ||
| 268 | */ | ||
| 269 | if (rv <= 0) { | ||
| 270 | ASN1error(ERR_R_EVP_LIB); | ||
| 271 | goto err; | ||
| 272 | } | ||
| 273 | } | 260 | } |
| 274 | 261 | ||
| 275 | if (rv == 2) { | 262 | sign_param = V_ASN1_UNDEF; |
| 276 | if ((type = EVP_MD_CTX_md(ctx)) == NULL) { | 263 | if (pkey->ameth->pkey_flags & ASN1_PKEY_SIGPARAM_NULL) |
| 277 | ASN1error(ASN1_R_CONTEXT_NOT_INITIALISED); | 264 | sign_param = V_ASN1_NULL; |
| 278 | return 0; | ||
| 279 | } | ||
| 280 | 265 | ||
| 281 | if (!OBJ_find_sigid_by_algs(&signid, EVP_MD_nid(type), | 266 | if (algor1 != NULL) { |
| 282 | pkey->ameth->pkey_id)) { | 267 | if (!X509_ALGOR_set0(algor1, aobj, sign_param, NULL)) |
| 283 | ASN1error(ASN1_R_DIGEST_AND_KEY_TYPE_NOT_SUPPORTED); | ||
| 284 | return 0; | 268 | return 0; |
| 285 | } | 269 | } |
| 286 | 270 | if (algor2 != NULL) { | |
| 287 | if (pkey->ameth->pkey_flags & ASN1_PKEY_SIGPARAM_NULL) | 271 | if (!X509_ALGOR_set0(algor2, aobj, sign_param, NULL)) |
| 288 | paramtype = V_ASN1_NULL; | 272 | return 0; |
| 289 | else | 273 | } |
| 290 | paramtype = V_ASN1_UNDEF; | ||
| 291 | 274 | ||
| 292 | if (algor1) | 275 | return 1; |
| 293 | X509_ALGOR_set0(algor1, | 276 | } |
| 294 | OBJ_nid2obj(signid), paramtype, NULL); | ||
| 295 | if (algor2) | ||
| 296 | X509_ALGOR_set0(algor2, | ||
| 297 | OBJ_nid2obj(signid), paramtype, NULL); | ||
| 298 | 277 | ||
| 299 | } | 278 | static int |
| 279 | asn1_item_sign(EVP_MD_CTX *ctx, const ASN1_ITEM *it, void *asn, | ||
| 280 | ASN1_BIT_STRING *signature) | ||
| 281 | { | ||
| 282 | unsigned char *in = NULL, *out = NULL; | ||
| 283 | size_t out_len = 0; | ||
| 284 | int in_len = 0; | ||
| 285 | int ret = 0; | ||
| 300 | 286 | ||
| 301 | if ((in_len = ASN1_item_i2d(asn, &in, it)) <= 0) { | 287 | if ((in_len = ASN1_item_i2d(asn, &in, it)) <= 0) { |
| 302 | in_len = 0; | 288 | in_len = 0; |
| @@ -325,14 +311,14 @@ ASN1_item_sign_ctx(const ASN1_ITEM *it, X509_ALGOR *algor1, X509_ALGOR *algor2, | |||
| 325 | out = NULL; | 311 | out = NULL; |
| 326 | 312 | ||
| 327 | if (!asn1_abs_set_unused_bits(signature, 0)) { | 313 | if (!asn1_abs_set_unused_bits(signature, 0)) { |
| 314 | ASN1_STRING_set0(signature, NULL, 0); | ||
| 328 | ASN1error(ERR_R_ASN1_LIB); | 315 | ASN1error(ERR_R_ASN1_LIB); |
| 329 | goto err; | 316 | goto err; |
| 330 | } | 317 | } |
| 331 | 318 | ||
| 332 | done: | 319 | ret = 1; |
| 333 | ret = out_len; | 320 | |
| 334 | err: | 321 | err: |
| 335 | EVP_MD_CTX_cleanup(ctx); | ||
| 336 | freezero(in, in_len); | 322 | freezero(in, in_len); |
| 337 | freezero(out, out_len); | 323 | freezero(out, out_len); |
| 338 | 324 | ||
| @@ -340,6 +326,55 @@ ASN1_item_sign_ctx(const ASN1_ITEM *it, X509_ALGOR *algor1, X509_ALGOR *algor2, | |||
| 340 | } | 326 | } |
| 341 | 327 | ||
| 342 | int | 328 | int |
| 329 | ASN1_item_sign_ctx(const ASN1_ITEM *it, X509_ALGOR *algor1, X509_ALGOR *algor2, | ||
| 330 | ASN1_BIT_STRING *signature, void *asn, EVP_MD_CTX *ctx) | ||
| 331 | { | ||
| 332 | EVP_PKEY *pkey; | ||
| 333 | int rv; | ||
| 334 | int ret = 0; | ||
| 335 | |||
| 336 | if ((pkey = EVP_PKEY_CTX_get0_pkey(ctx->pctx)) == NULL) { | ||
| 337 | ASN1error(ASN1_R_CONTEXT_NOT_INITIALISED); | ||
| 338 | goto err; | ||
| 339 | } | ||
| 340 | if (pkey->ameth == NULL) { | ||
| 341 | ASN1error(ASN1_R_DIGEST_AND_KEY_TYPE_NOT_SUPPORTED); | ||
| 342 | goto err; | ||
| 343 | } | ||
| 344 | |||
| 345 | /* | ||
| 346 | * API insanity ahead. If the item_sign() method is absent or if it | ||
| 347 | * returns 2, this means: do all the work here. If it returns 3, only | ||
| 348 | * sign. If it returns 1, then there's nothing to do but to return | ||
| 349 | * the signature's length. Everything else is an error. | ||
| 350 | */ | ||
| 351 | |||
| 352 | rv = 2; | ||
| 353 | if (pkey->ameth->item_sign != NULL) | ||
| 354 | rv = pkey->ameth->item_sign(ctx, it, asn, algor1, algor2, | ||
| 355 | signature); | ||
| 356 | if (rv <= 0 || rv > 3) | ||
| 357 | goto err; | ||
| 358 | if (rv == 1) | ||
| 359 | goto done; | ||
| 360 | if (rv == 2) { | ||
| 361 | if (!asn1_item_set_algorithm_identifiers(ctx, algor1, algor2)) | ||
| 362 | goto err; | ||
| 363 | } | ||
| 364 | |||
| 365 | if (!asn1_item_sign(ctx, it, asn, signature)) | ||
| 366 | goto err; | ||
| 367 | |||
| 368 | done: | ||
| 369 | ret = signature->length; | ||
| 370 | |||
| 371 | err: | ||
| 372 | EVP_MD_CTX_cleanup(ctx); | ||
| 373 | |||
| 374 | return ret; | ||
| 375 | } | ||
| 376 | |||
| 377 | int | ||
| 343 | ASN1_item_verify(const ASN1_ITEM *it, X509_ALGOR *a, | 378 | ASN1_item_verify(const ASN1_ITEM *it, X509_ALGOR *a, |
| 344 | ASN1_BIT_STRING *signature, void *asn, EVP_PKEY *pkey) | 379 | ASN1_BIT_STRING *signature, void *asn, EVP_PKEY *pkey) |
| 345 | { | 380 | { |
