summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortb <>2023-07-13 20:59:10 +0000
committertb <>2023-07-13 20:59:10 +0000
commit621f19e56aa0abe5b71795a2f7e1fae064f180d9 (patch)
tree740cee1b580b36bcf1ccf6709a9cd002c6b501db
parentff23a256acb3524bbe45483e0147fee9accf46c9 (diff)
downloadopenbsd-621f19e56aa0abe5b71795a2f7e1fae064f180d9.tar.gz
openbsd-621f19e56aa0abe5b71795a2f7e1fae064f180d9.tar.bz2
openbsd-621f19e56aa0abe5b71795a2f7e1fae064f180d9.zip
Refactor ASN1_item_sign_ctx()
Oh, joy! The muppets had a feast: they could combine the horrors of EVP with X.509... Return values between -1 and 3 indicating how much work needs to be done, depending on whether methods are present or absent. Needless to say that RSA and EdDSA had inconsistent return values until recently. Instead of interleaving if/else branches, split out two helper functions that do essentially independent things, which results in something that isn't entirely bad. Well, at least not compared to the surrounding code. asn1_item_set_algorithm_identifiers() extracts the signature algorithm from the digest and pkey if known, and sets it on the two X509_ALGOR that may or may not have been passed in. asn1_item_sign() converts data into der and signs. Of course there were also a few leaks and missing error checks. ok jsing
-rw-r--r--src/lib/libcrypto/asn1/asn1_item.c143
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
233int 233static int
234ASN1_item_sign_ctx(const ASN1_ITEM *it, X509_ALGOR *algor1, X509_ALGOR *algor2, 234asn1_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 } 278static int
279asn1_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
342int 328int
329ASN1_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
377int
343ASN1_item_verify(const ASN1_ITEM *it, X509_ALGOR *a, 378ASN1_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{