diff options
Diffstat (limited to 'src/eddsa.c')
-rw-r--r-- | src/eddsa.c | 169 |
1 files changed, 169 insertions, 0 deletions
diff --git a/src/eddsa.c b/src/eddsa.c new file mode 100644 index 0000000..92a0222 --- /dev/null +++ b/src/eddsa.c | |||
@@ -0,0 +1,169 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2019 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/bn.h> | ||
8 | #include <openssl/ec.h> | ||
9 | #include <openssl/evp.h> | ||
10 | #include <openssl/obj_mac.h> | ||
11 | |||
12 | #include <string.h> | ||
13 | #include "fido.h" | ||
14 | #include "fido/eddsa.h" | ||
15 | |||
16 | #if defined(LIBRESSL_VERSION_NUMBER) || OPENSSL_VERSION_NUMBER < 0x10101000L | ||
17 | EVP_PKEY * | ||
18 | EVP_PKEY_new_raw_public_key(int type, ENGINE *e, const unsigned char *key, | ||
19 | size_t keylen) | ||
20 | { | ||
21 | (void)type; | ||
22 | (void)e; | ||
23 | (void)key; | ||
24 | (void)keylen; | ||
25 | |||
26 | return (NULL); | ||
27 | } | ||
28 | |||
29 | int | ||
30 | EVP_PKEY_get_raw_public_key(const EVP_PKEY *pkey, unsigned char *pub, | ||
31 | size_t *len) | ||
32 | { | ||
33 | (void)pkey; | ||
34 | (void)pub; | ||
35 | (void)len; | ||
36 | |||
37 | return (0); | ||
38 | } | ||
39 | |||
40 | int | ||
41 | EVP_DigestVerify(EVP_MD_CTX *ctx, const unsigned char *sigret, size_t siglen, | ||
42 | const unsigned char *tbs, size_t tbslen) | ||
43 | { | ||
44 | (void)ctx; | ||
45 | (void)sigret; | ||
46 | (void)siglen; | ||
47 | (void)tbs; | ||
48 | (void)tbslen; | ||
49 | |||
50 | return (0); | ||
51 | } | ||
52 | #endif /* LIBRESSL_VERSION_NUMBER || OPENSSL_VERSION_NUMBER < 0x10101000L */ | ||
53 | |||
54 | #if OPENSSL_VERSION_NUMBER < 0x10100000L | ||
55 | EVP_MD_CTX * | ||
56 | EVP_MD_CTX_new(void) | ||
57 | { | ||
58 | return (NULL); | ||
59 | } | ||
60 | |||
61 | void | ||
62 | EVP_MD_CTX_free(EVP_MD_CTX *ctx) | ||
63 | { | ||
64 | (void)ctx; | ||
65 | } | ||
66 | #endif /* OPENSSL_VERSION_NUMBER < 0x10100000L */ | ||
67 | |||
68 | static int | ||
69 | decode_coord(const cbor_item_t *item, void *xy, size_t xy_len) | ||
70 | { | ||
71 | if (cbor_isa_bytestring(item) == false || | ||
72 | cbor_bytestring_is_definite(item) == false || | ||
73 | cbor_bytestring_length(item) != xy_len) { | ||
74 | fido_log_debug("%s: cbor type", __func__); | ||
75 | return (-1); | ||
76 | } | ||
77 | |||
78 | memcpy(xy, cbor_bytestring_handle(item), xy_len); | ||
79 | |||
80 | return (0); | ||
81 | } | ||
82 | |||
83 | static int | ||
84 | decode_pubkey_point(const cbor_item_t *key, const cbor_item_t *val, void *arg) | ||
85 | { | ||
86 | eddsa_pk_t *k = arg; | ||
87 | |||
88 | if (cbor_isa_negint(key) == false || | ||
89 | cbor_int_get_width(key) != CBOR_INT_8) | ||
90 | return (0); /* ignore */ | ||
91 | |||
92 | switch (cbor_get_uint8(key)) { | ||
93 | case 1: /* x coordinate */ | ||
94 | return (decode_coord(val, &k->x, sizeof(k->x))); | ||
95 | } | ||
96 | |||
97 | return (0); /* ignore */ | ||
98 | } | ||
99 | |||
100 | int | ||
101 | eddsa_pk_decode(const cbor_item_t *item, eddsa_pk_t *k) | ||
102 | { | ||
103 | if (cbor_isa_map(item) == false || | ||
104 | cbor_map_is_definite(item) == false || | ||
105 | cbor_map_iter(item, k, decode_pubkey_point) < 0) { | ||
106 | fido_log_debug("%s: cbor type", __func__); | ||
107 | return (-1); | ||
108 | } | ||
109 | |||
110 | return (0); | ||
111 | } | ||
112 | |||
113 | eddsa_pk_t * | ||
114 | eddsa_pk_new(void) | ||
115 | { | ||
116 | return (calloc(1, sizeof(eddsa_pk_t))); | ||
117 | } | ||
118 | |||
119 | void | ||
120 | eddsa_pk_free(eddsa_pk_t **pkp) | ||
121 | { | ||
122 | eddsa_pk_t *pk; | ||
123 | |||
124 | if (pkp == NULL || (pk = *pkp) == NULL) | ||
125 | return; | ||
126 | |||
127 | explicit_bzero(pk, sizeof(*pk)); | ||
128 | free(pk); | ||
129 | |||
130 | *pkp = NULL; | ||
131 | } | ||
132 | |||
133 | int | ||
134 | eddsa_pk_from_ptr(eddsa_pk_t *pk, const void *ptr, size_t len) | ||
135 | { | ||
136 | if (len < sizeof(*pk)) | ||
137 | return (FIDO_ERR_INVALID_ARGUMENT); | ||
138 | |||
139 | memcpy(pk, ptr, sizeof(*pk)); | ||
140 | |||
141 | return (FIDO_OK); | ||
142 | } | ||
143 | |||
144 | EVP_PKEY * | ||
145 | eddsa_pk_to_EVP_PKEY(const eddsa_pk_t *k) | ||
146 | { | ||
147 | EVP_PKEY *pkey = NULL; | ||
148 | |||
149 | if ((pkey = EVP_PKEY_new_raw_public_key(EVP_PKEY_ED25519, NULL, k->x, | ||
150 | sizeof(k->x))) == NULL) | ||
151 | fido_log_debug("%s: EVP_PKEY_new_raw_public_key", __func__); | ||
152 | |||
153 | return (pkey); | ||
154 | } | ||
155 | |||
156 | int | ||
157 | eddsa_pk_from_EVP_PKEY(eddsa_pk_t *pk, const EVP_PKEY *pkey) | ||
158 | { | ||
159 | size_t len = 0; | ||
160 | |||
161 | if (EVP_PKEY_get_raw_public_key(pkey, NULL, &len) != 1 || | ||
162 | len != sizeof(pk->x)) | ||
163 | return (FIDO_ERR_INTERNAL); | ||
164 | if (EVP_PKEY_get_raw_public_key(pkey, pk->x, &len) != 1 || | ||
165 | len != sizeof(pk->x)) | ||
166 | return (FIDO_ERR_INTERNAL); | ||
167 | |||
168 | return (FIDO_OK); | ||
169 | } | ||