diff options
Diffstat (limited to 'src/ecdh.c')
-rw-r--r-- | src/ecdh.c | 121 |
1 files changed, 121 insertions, 0 deletions
diff --git a/src/ecdh.c b/src/ecdh.c new file mode 100644 index 0000000..7f25c7b --- /dev/null +++ b/src/ecdh.c | |||
@@ -0,0 +1,121 @@ | |||
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 | { | ||
16 | EVP_PKEY *pk_evp = NULL; | ||
17 | EVP_PKEY *sk_evp = NULL; | ||
18 | EVP_PKEY_CTX *ctx = NULL; | ||
19 | fido_blob_t *secret = NULL; | ||
20 | int ok = -1; | ||
21 | |||
22 | *ecdh = NULL; | ||
23 | |||
24 | /* allocate blobs for secret & ecdh */ | ||
25 | if ((secret = fido_blob_new()) == NULL || | ||
26 | (*ecdh = fido_blob_new()) == NULL) | ||
27 | goto fail; | ||
28 | |||
29 | /* wrap the keys as openssl objects */ | ||
30 | if ((pk_evp = es256_pk_to_EVP_PKEY(pk)) == NULL || | ||
31 | (sk_evp = es256_sk_to_EVP_PKEY(sk)) == NULL) { | ||
32 | fido_log_debug("%s: es256_to_EVP_PKEY", __func__); | ||
33 | goto fail; | ||
34 | } | ||
35 | |||
36 | /* set ecdh parameters */ | ||
37 | if ((ctx = EVP_PKEY_CTX_new(sk_evp, NULL)) == NULL || | ||
38 | EVP_PKEY_derive_init(ctx) <= 0 || | ||
39 | EVP_PKEY_derive_set_peer(ctx, pk_evp) <= 0) { | ||
40 | fido_log_debug("%s: EVP_PKEY_derive_init", __func__); | ||
41 | goto fail; | ||
42 | } | ||
43 | |||
44 | /* perform ecdh */ | ||
45 | if (EVP_PKEY_derive(ctx, NULL, &secret->len) <= 0 || | ||
46 | (secret->ptr = calloc(1, secret->len)) == NULL || | ||
47 | EVP_PKEY_derive(ctx, secret->ptr, &secret->len) <= 0) { | ||
48 | fido_log_debug("%s: EVP_PKEY_derive", __func__); | ||
49 | goto fail; | ||
50 | } | ||
51 | |||
52 | /* use sha256 as a kdf on the resulting secret */ | ||
53 | (*ecdh)->len = SHA256_DIGEST_LENGTH; | ||
54 | if (((*ecdh)->ptr = calloc(1, (*ecdh)->len)) == NULL || | ||
55 | SHA256(secret->ptr, secret->len, (*ecdh)->ptr) != (*ecdh)->ptr) { | ||
56 | fido_log_debug("%s: sha256", __func__); | ||
57 | goto fail; | ||
58 | } | ||
59 | |||
60 | ok = 0; | ||
61 | fail: | ||
62 | if (pk_evp != NULL) | ||
63 | EVP_PKEY_free(pk_evp); | ||
64 | if (sk_evp != NULL) | ||
65 | EVP_PKEY_free(sk_evp); | ||
66 | if (ctx != NULL) | ||
67 | EVP_PKEY_CTX_free(ctx); | ||
68 | if (ok < 0) | ||
69 | fido_blob_free(ecdh); | ||
70 | |||
71 | fido_blob_free(&secret); | ||
72 | |||
73 | return (ok); | ||
74 | } | ||
75 | |||
76 | int | ||
77 | fido_do_ecdh(fido_dev_t *dev, es256_pk_t **pk, fido_blob_t **ecdh) | ||
78 | { | ||
79 | es256_sk_t *sk = NULL; /* our private key */ | ||
80 | es256_pk_t *ak = NULL; /* authenticator's public key */ | ||
81 | int r; | ||
82 | |||
83 | *pk = NULL; /* our public key; returned */ | ||
84 | *ecdh = NULL; /* shared ecdh secret; returned */ | ||
85 | |||
86 | if ((sk = es256_sk_new()) == NULL || (*pk = es256_pk_new()) == NULL) { | ||
87 | r = FIDO_ERR_INTERNAL; | ||
88 | goto fail; | ||
89 | } | ||
90 | |||
91 | if (es256_sk_create(sk) < 0 || es256_derive_pk(sk, *pk) < 0) { | ||
92 | fido_log_debug("%s: es256_derive_pk", __func__); | ||
93 | r = FIDO_ERR_INTERNAL; | ||
94 | goto fail; | ||
95 | } | ||
96 | |||
97 | if ((ak = es256_pk_new()) == NULL || | ||
98 | fido_dev_authkey(dev, ak) != FIDO_OK) { | ||
99 | fido_log_debug("%s: fido_dev_authkey", __func__); | ||
100 | r = FIDO_ERR_INTERNAL; | ||
101 | goto fail; | ||
102 | } | ||
103 | |||
104 | if (do_ecdh(sk, ak, ecdh) < 0) { | ||
105 | fido_log_debug("%s: do_ecdh", __func__); | ||
106 | r = FIDO_ERR_INTERNAL; | ||
107 | goto fail; | ||
108 | } | ||
109 | |||
110 | r = FIDO_OK; | ||
111 | fail: | ||
112 | es256_sk_free(&sk); | ||
113 | es256_pk_free(&ak); | ||
114 | |||
115 | if (r != FIDO_OK) { | ||
116 | es256_pk_free(pk); | ||
117 | fido_blob_free(ecdh); | ||
118 | } | ||
119 | |||
120 | return (r); | ||
121 | } | ||