Coverage Report

Created: 2020-03-07 10:10

/libfido2/src/ecdh.c
Line
Count
Source
1
/*
2
 * Copyright (c) 2018 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
 */
6
7
#include <openssl/evp.h>
8
#include <openssl/sha.h>
9
10
#include "fido.h"
11
#include "fido/es256.h"
12
13
static int
14
do_ecdh(const es256_sk_t *sk, const es256_pk_t *pk, fido_blob_t **ecdh)
15
7.08k
{
16
7.08k
        EVP_PKEY        *pk_evp = NULL;
17
7.08k
        EVP_PKEY        *sk_evp = NULL;
18
7.08k
        EVP_PKEY_CTX    *ctx = NULL;
19
7.08k
        fido_blob_t     *secret = NULL;
20
7.08k
        int              ok = -1;
21
7.08k
22
7.08k
        *ecdh = NULL;
23
7.08k
24
7.08k
        /* allocate blobs for secret & ecdh */
25
7.08k
        if ((secret = fido_blob_new()) == NULL ||
26
7.08k
            (*ecdh = fido_blob_new()) == NULL)
27
7.08k
                goto fail;
28
7.05k
29
7.05k
        /* wrap the keys as openssl objects */
30
7.05k
        if ((pk_evp = es256_pk_to_EVP_PKEY(pk)) == NULL ||
31
7.05k
            (sk_evp = es256_sk_to_EVP_PKEY(sk)) == NULL) {
32
2.47k
                fido_log_debug("%s: es256_to_EVP_PKEY", __func__);
33
2.47k
                goto fail;
34
2.47k
        }
35
4.57k
36
4.57k
        /* set ecdh parameters */
37
4.57k
        if ((ctx = EVP_PKEY_CTX_new(sk_evp, NULL)) == NULL ||
38
4.57k
            EVP_PKEY_derive_init(ctx) <= 0 ||
39
4.57k
            EVP_PKEY_derive_set_peer(ctx, pk_evp) <= 0) {
40
76
                fido_log_debug("%s: EVP_PKEY_derive_init", __func__);
41
76
                goto fail;
42
76
        }
43
4.50k
44
4.50k
        /* perform ecdh */
45
4.50k
        if (EVP_PKEY_derive(ctx, NULL, &secret->len) <= 0 ||
46
4.50k
            (secret->ptr = calloc(1, secret->len)) == NULL ||
47
4.50k
            EVP_PKEY_derive(ctx, secret->ptr, &secret->len) <= 0) {
48
24
                fido_log_debug("%s: EVP_PKEY_derive", __func__);
49
24
                goto fail;
50
24
        }
51
4.47k
52
4.47k
        /* use sha256 as a kdf on the resulting secret */
53
4.47k
        (*ecdh)->len = SHA256_DIGEST_LENGTH;
54
4.47k
        if (((*ecdh)->ptr = calloc(1, (*ecdh)->len)) == NULL ||
55
4.47k
            SHA256(secret->ptr, secret->len, (*ecdh)->ptr) != (*ecdh)->ptr) {
56
29
                fido_log_debug("%s: sha256", __func__);
57
29
                goto fail;
58
29
        }
59
4.44k
60
4.44k
        ok = 0;
61
7.08k
fail:
62
7.08k
        if (pk_evp != NULL)
63
7.08k
                EVP_PKEY_free(pk_evp);
64
7.08k
        if (sk_evp != NULL)
65
7.08k
                EVP_PKEY_free(sk_evp);
66
7.08k
        if (ctx != NULL)
67
7.08k
                EVP_PKEY_CTX_free(ctx);
68
7.08k
        if (ok < 0)
69
2.63k
                fido_blob_free(ecdh);
70
7.08k
71
7.08k
        fido_blob_free(&secret);
72
7.08k
73
7.08k
        return (ok);
74
4.44k
}
75
76
int
77
fido_do_ecdh(fido_dev_t *dev, es256_pk_t **pk, fido_blob_t **ecdh)
78
13.9k
{
79
13.9k
        es256_sk_t      *sk = NULL; /* our private key */
80
13.9k
        es256_pk_t      *ak = NULL; /* authenticator's public key */
81
13.9k
        int              r;
82
13.9k
83
13.9k
        *pk = NULL; /* our public key; returned */
84
13.9k
        *ecdh = NULL; /* shared ecdh secret; returned */
85
13.9k
86
13.9k
        if ((sk = es256_sk_new()) == NULL || (*pk = es256_pk_new()) == NULL) {
87
39
                r = FIDO_ERR_INTERNAL;
88
39
                goto fail;
89
39
        }
90
13.9k
91
13.9k
        if (es256_sk_create(sk) < 0 || es256_derive_pk(sk, *pk) < 0) {
92
755
                fido_log_debug("%s: es256_derive_pk", __func__);
93
755
                r = FIDO_ERR_INTERNAL;
94
755
                goto fail;
95
755
        }
96
13.1k
97
13.1k
        if ((ak = es256_pk_new()) == NULL ||
98
13.1k
            fido_dev_authkey(dev, ak) != FIDO_OK) {
99
6.09k
                fido_log_debug("%s: fido_dev_authkey", __func__);
100
6.09k
                r = FIDO_ERR_INTERNAL;
101
6.09k
                goto fail;
102
6.09k
        }
103
7.08k
104
7.08k
        if (do_ecdh(sk, ak, ecdh) < 0) {
105
2.63k
                fido_log_debug("%s: do_ecdh", __func__);
106
2.63k
                r = FIDO_ERR_INTERNAL;
107
2.63k
                goto fail;
108
2.63k
        }
109
4.44k
110
4.44k
        r = FIDO_OK;
111
13.9k
fail:
112
13.9k
        es256_sk_free(&sk);
113
13.9k
        es256_pk_free(&ak);
114
13.9k
115
13.9k
        if (r != FIDO_OK) {
116
9.52k
                es256_pk_free(pk);
117
9.52k
                fido_blob_free(ecdh);
118
9.52k
        }
119
13.9k
120
13.9k
        return (r);
121
4.44k
}