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 fido_log_debug("%s: unimplemented", __func__); 27 28 return (NULL); 29 } 30 31 int 32 EVP_PKEY_get_raw_public_key(const EVP_PKEY *pkey, unsigned char *pub, 33 size_t *len) 34 { 35 (void)pkey; 36 (void)pub; 37 (void)len; 38 39 fido_log_debug("%s: unimplemented", __func__); 40 41 return (0); 42 } 43 44 int 45 EVP_DigestVerify(EVP_MD_CTX *ctx, const unsigned char *sigret, size_t siglen, 46 const unsigned char *tbs, size_t tbslen) 47 { 48 (void)ctx; 49 (void)sigret; 50 (void)siglen; 51 (void)tbs; 52 (void)tbslen; 53 54 fido_log_debug("%s: unimplemented", __func__); 55 56 return (0); 57 } 58 #endif /* LIBRESSL_VERSION_NUMBER || OPENSSL_VERSION_NUMBER < 0x10101000L */ 59 60 #if OPENSSL_VERSION_NUMBER < 0x10100000L 61 EVP_MD_CTX * 62 EVP_MD_CTX_new(void) 63 { 64 fido_log_debug("%s: unimplemented", __func__); 65 66 return (NULL); 67 } 68 69 void 70 EVP_MD_CTX_free(EVP_MD_CTX *ctx) 71 { 72 (void)ctx; 73 } 74 #endif /* OPENSSL_VERSION_NUMBER < 0x10100000L */ 75 76 static int 77 decode_coord(const cbor_item_t *item, void *xy, size_t xy_len) 78 { 79 if (cbor_isa_bytestring(item) == false || 80 cbor_bytestring_is_definite(item) == false || 81 cbor_bytestring_length(item) != xy_len) { 82 fido_log_debug("%s: cbor type", __func__); 83 return (-1); 84 } 85 86 memcpy(xy, cbor_bytestring_handle(item), xy_len); 87 88 return (0); 89 } 90 91 static int 92 decode_pubkey_point(const cbor_item_t *key, const cbor_item_t *val, void *arg) 93 { 94 eddsa_pk_t *k = arg; 95 96 if (cbor_isa_negint(key) == false || 97 cbor_int_get_width(key) != CBOR_INT_8) 98 return (0); /* ignore */ 99 100 switch (cbor_get_uint8(key)) { 101 case 1: /* x coordinate */ 102 return (decode_coord(val, &k->x, sizeof(k->x))); 103 } 104 105 return (0); /* ignore */ 106 } 107 108 int 109 eddsa_pk_decode(const cbor_item_t *item, eddsa_pk_t *k) 110 { 111 if (cbor_isa_map(item) == false || 112 cbor_map_is_definite(item) == false || 113 cbor_map_iter(item, k, decode_pubkey_point) < 0) { 114 fido_log_debug("%s: cbor type", __func__); 115 return (-1); 116 } 117 118 return (0); 119 } 120 121 eddsa_pk_t * 122 eddsa_pk_new(void) 123 { 124 return (calloc(1, sizeof(eddsa_pk_t))); 125 } 126 127 void 128 eddsa_pk_free(eddsa_pk_t **pkp) 129 { 130 eddsa_pk_t *pk; 131 132 if (pkp == NULL || (pk = *pkp) == NULL) 133 return; 134 135 explicit_bzero(pk, sizeof(*pk)); 136 free(pk); 137 138 *pkp = NULL; 139 } 140 141 int 142 eddsa_pk_from_ptr(eddsa_pk_t *pk, const void *ptr, size_t len) 143 { 144 if (len < sizeof(*pk)) 145 return (FIDO_ERR_INVALID_ARGUMENT); 146 147 memcpy(pk, ptr, sizeof(*pk)); 148 149 return (FIDO_OK); 150 } 151 152 EVP_PKEY * 153 eddsa_pk_to_EVP_PKEY(const eddsa_pk_t *k) 154 { 155 EVP_PKEY *pkey = NULL; 156 157 if ((pkey = EVP_PKEY_new_raw_public_key(EVP_PKEY_ED25519, NULL, k->x, 158 sizeof(k->x))) == NULL) 159 fido_log_debug("%s: EVP_PKEY_new_raw_public_key", __func__); 160 161 return (pkey); 162 } 163 164 int 165 eddsa_pk_from_EVP_PKEY(eddsa_pk_t *pk, const EVP_PKEY *pkey) 166 { 167 size_t len = 0; 168 169 if (EVP_PKEY_get_raw_public_key(pkey, NULL, &len) != 1 || 170 len != sizeof(pk->x)) 171 return (FIDO_ERR_INTERNAL); 172 if (EVP_PKEY_get_raw_public_key(pkey, pk->x, &len) != 1 || 173 len != sizeof(pk->x)) 174 return (FIDO_ERR_INTERNAL); 175 176 return (FIDO_OK); 177 } 178