1 /*
2 * Copyright (c) 2021 Yubico AB. All rights reserved.
3 * Use of this source code is governed by a BSD-style
4 * license that can be found in the LICENSE file.
5 * SPDX-License-Identifier: BSD-2-Clause
6 */
7
8 #include <openssl/rsa.h>
9 #include <openssl/obj_mac.h>
10
11 #include "fido.h"
12
13 #if defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x3050200fL
14 static EVP_MD *
rs1_get_EVP_MD(void)15 rs1_get_EVP_MD(void)
16 {
17 const EVP_MD *from;
18 EVP_MD *to = NULL;
19
20 if ((from = EVP_sha1()) != NULL && (to = malloc(sizeof(*to))) != NULL)
21 memcpy(to, from, sizeof(*to));
22
23 return (to);
24 }
25
26 static void
rs1_free_EVP_MD(EVP_MD * md)27 rs1_free_EVP_MD(EVP_MD *md)
28 {
29 freezero(md, sizeof(*md));
30 }
31 #elif OPENSSL_VERSION_NUMBER >= 0x30000000
32 static EVP_MD *
rs1_get_EVP_MD(void)33 rs1_get_EVP_MD(void)
34 {
35 return (EVP_MD_fetch(NULL, "SHA-1", NULL));
36 }
37
38 static void
rs1_free_EVP_MD(EVP_MD * md)39 rs1_free_EVP_MD(EVP_MD *md)
40 {
41 EVP_MD_free(md);
42 }
43 #else
44 static EVP_MD *
rs1_get_EVP_MD(void)45 rs1_get_EVP_MD(void)
46 {
47 const EVP_MD *md;
48
49 if ((md = EVP_sha1()) == NULL)
50 return (NULL);
51
52 return (EVP_MD_meth_dup(md));
53 }
54
55 static void
rs1_free_EVP_MD(EVP_MD * md)56 rs1_free_EVP_MD(EVP_MD *md)
57 {
58 EVP_MD_meth_free(md);
59 }
60 #endif /* LIBRESSL_VERSION_NUMBER */
61
62 int
rs1_verify_sig(const fido_blob_t * dgst,EVP_PKEY * pkey,const fido_blob_t * sig)63 rs1_verify_sig(const fido_blob_t *dgst, EVP_PKEY *pkey,
64 const fido_blob_t *sig)
65 {
66 EVP_PKEY_CTX *pctx = NULL;
67 EVP_MD *md = NULL;
68 int ok = -1;
69
70 if (EVP_PKEY_base_id(pkey) != EVP_PKEY_RSA) {
71 fido_log_debug("%s: EVP_PKEY_base_id", __func__);
72 goto fail;
73 }
74
75 if ((md = rs1_get_EVP_MD()) == NULL) {
76 fido_log_debug("%s: rs1_get_EVP_MD", __func__);
77 goto fail;
78 }
79
80 if ((pctx = EVP_PKEY_CTX_new(pkey, NULL)) == NULL ||
81 EVP_PKEY_verify_init(pctx) != 1 ||
82 EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PADDING) != 1 ||
83 EVP_PKEY_CTX_set_signature_md(pctx, md) != 1) {
84 fido_log_debug("%s: EVP_PKEY_CTX", __func__);
85 goto fail;
86 }
87
88 if (EVP_PKEY_verify(pctx, sig->ptr, sig->len, dgst->ptr,
89 dgst->len) != 1) {
90 fido_log_debug("%s: EVP_PKEY_verify", __func__);
91 goto fail;
92 }
93
94 ok = 0;
95 fail:
96 EVP_PKEY_CTX_free(pctx);
97 rs1_free_EVP_MD(md);
98
99 return (ok);
100 }
101