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