1 /* 2 * Copyright (c) 2018-2021 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/rsa.h> 9 #include <openssl/obj_mac.h> 10 11 #include "fido.h" 12 #include "fido/rs256.h" 13 14 #if defined(LIBRESSL_VERSION_NUMBER) 15 static EVP_MD * 16 rs256_get_EVP_MD(void) 17 { 18 const EVP_MD *from; 19 EVP_MD *to = NULL; 20 21 if ((from = EVP_sha256()) != NULL && (to = malloc(sizeof(*to))) != NULL) 22 memcpy(to, from, sizeof(*to)); 23 24 return (to); 25 } 26 27 static void 28 rs256_free_EVP_MD(EVP_MD *md) 29 { 30 freezero(md, sizeof(*md)); 31 } 32 #elif OPENSSL_VERSION_NUMBER >= 0x30000000 33 static EVP_MD * 34 rs256_get_EVP_MD(void) 35 { 36 return (EVP_MD_fetch(NULL, "SHA2-256", NULL)); 37 } 38 39 static void 40 rs256_free_EVP_MD(EVP_MD *md) 41 { 42 EVP_MD_free(md); 43 } 44 #else 45 static EVP_MD * 46 rs256_get_EVP_MD(void) 47 { 48 const EVP_MD *md; 49 50 if ((md = EVP_sha256()) == NULL) 51 return (NULL); 52 53 return (EVP_MD_meth_dup(md)); 54 } 55 56 static void 57 rs256_free_EVP_MD(EVP_MD *md) 58 { 59 EVP_MD_meth_free(md); 60 } 61 #endif /* LIBRESSL_VERSION_NUMBER */ 62 63 static int 64 decode_bignum(const cbor_item_t *item, void *ptr, size_t len) 65 { 66 if (cbor_isa_bytestring(item) == false || 67 cbor_bytestring_is_definite(item) == false || 68 cbor_bytestring_length(item) != len) { 69 fido_log_debug("%s: cbor type", __func__); 70 return (-1); 71 } 72 73 memcpy(ptr, cbor_bytestring_handle(item), len); 74 75 return (0); 76 } 77 78 static int 79 decode_rsa_pubkey(const cbor_item_t *key, const cbor_item_t *val, void *arg) 80 { 81 rs256_pk_t *k = arg; 82 83 if (cbor_isa_negint(key) == false || 84 cbor_int_get_width(key) != CBOR_INT_8) 85 return (0); /* ignore */ 86 87 switch (cbor_get_uint8(key)) { 88 case 0: /* modulus */ 89 return (decode_bignum(val, &k->n, sizeof(k->n))); 90 case 1: /* public exponent */ 91 return (decode_bignum(val, &k->e, sizeof(k->e))); 92 } 93 94 return (0); /* ignore */ 95 } 96 97 int 98 rs256_pk_decode(const cbor_item_t *item, rs256_pk_t *k) 99 { 100 if (cbor_isa_map(item) == false || 101 cbor_map_is_definite(item) == false || 102 cbor_map_iter(item, k, decode_rsa_pubkey) < 0) { 103 fido_log_debug("%s: cbor type", __func__); 104 return (-1); 105 } 106 107 return (0); 108 } 109 110 rs256_pk_t * 111 rs256_pk_new(void) 112 { 113 return (calloc(1, sizeof(rs256_pk_t))); 114 } 115 116 void 117 rs256_pk_free(rs256_pk_t **pkp) 118 { 119 rs256_pk_t *pk; 120 121 if (pkp == NULL || (pk = *pkp) == NULL) 122 return; 123 124 freezero(pk, sizeof(*pk)); 125 *pkp = NULL; 126 } 127 128 int 129 rs256_pk_from_ptr(rs256_pk_t *pk, const void *ptr, size_t len) 130 { 131 if (len < sizeof(*pk)) 132 return (FIDO_ERR_INVALID_ARGUMENT); 133 134 memcpy(pk, ptr, sizeof(*pk)); 135 136 return (FIDO_OK); 137 } 138 139 EVP_PKEY * 140 rs256_pk_to_EVP_PKEY(const rs256_pk_t *k) 141 { 142 RSA *rsa = NULL; 143 EVP_PKEY *pkey = NULL; 144 BIGNUM *n = NULL; 145 BIGNUM *e = NULL; 146 int ok = -1; 147 148 if ((n = BN_new()) == NULL || (e = BN_new()) == NULL) 149 goto fail; 150 151 if (BN_bin2bn(k->n, sizeof(k->n), n) == NULL || 152 BN_bin2bn(k->e, sizeof(k->e), e) == NULL) { 153 fido_log_debug("%s: BN_bin2bn", __func__); 154 goto fail; 155 } 156 157 if ((rsa = RSA_new()) == NULL || RSA_set0_key(rsa, n, e, NULL) == 0) { 158 fido_log_debug("%s: RSA_set0_key", __func__); 159 goto fail; 160 } 161 162 /* at this point, n and e belong to rsa */ 163 n = NULL; 164 e = NULL; 165 166 if ((pkey = EVP_PKEY_new()) == NULL || 167 EVP_PKEY_assign_RSA(pkey, rsa) == 0) { 168 fido_log_debug("%s: EVP_PKEY_assign_RSA", __func__); 169 goto fail; 170 } 171 172 rsa = NULL; /* at this point, rsa belongs to evp */ 173 174 ok = 0; 175 fail: 176 if (n != NULL) 177 BN_free(n); 178 if (e != NULL) 179 BN_free(e); 180 if (rsa != NULL) 181 RSA_free(rsa); 182 if (ok < 0 && pkey != NULL) { 183 EVP_PKEY_free(pkey); 184 pkey = NULL; 185 } 186 187 return (pkey); 188 } 189 190 int 191 rs256_pk_from_RSA(rs256_pk_t *pk, const RSA *rsa) 192 { 193 const BIGNUM *n = NULL; 194 const BIGNUM *e = NULL; 195 const BIGNUM *d = NULL; 196 int k; 197 198 if (RSA_bits(rsa) != 2048) { 199 fido_log_debug("%s: invalid key length", __func__); 200 return (FIDO_ERR_INVALID_ARGUMENT); 201 } 202 203 RSA_get0_key(rsa, &n, &e, &d); 204 205 if (n == NULL || e == NULL) { 206 fido_log_debug("%s: RSA_get0_key", __func__); 207 return (FIDO_ERR_INTERNAL); 208 } 209 210 if ((k = BN_num_bytes(n)) < 0 || (size_t)k > sizeof(pk->n) || 211 (k = BN_num_bytes(e)) < 0 || (size_t)k > sizeof(pk->e)) { 212 fido_log_debug("%s: invalid key", __func__); 213 return (FIDO_ERR_INTERNAL); 214 } 215 216 if ((k = BN_bn2bin(n, pk->n)) < 0 || (size_t)k > sizeof(pk->n) || 217 (k = BN_bn2bin(e, pk->e)) < 0 || (size_t)k > sizeof(pk->e)) { 218 fido_log_debug("%s: BN_bn2bin", __func__); 219 return (FIDO_ERR_INTERNAL); 220 } 221 222 return (FIDO_OK); 223 } 224 225 int 226 rs256_pk_from_EVP_PKEY(rs256_pk_t *pk, const EVP_PKEY *pkey) 227 { 228 RSA *rsa; 229 230 if (EVP_PKEY_base_id(pkey) != EVP_PKEY_RSA || 231 (rsa = EVP_PKEY_get0(pkey)) == NULL) 232 return (FIDO_ERR_INVALID_ARGUMENT); 233 234 return (rs256_pk_from_RSA(pk, rsa)); 235 } 236 237 int 238 rs256_verify_sig(const fido_blob_t *dgst, EVP_PKEY *pkey, 239 const fido_blob_t *sig) 240 { 241 EVP_PKEY_CTX *pctx = NULL; 242 EVP_MD *md = NULL; 243 int ok = -1; 244 245 if (EVP_PKEY_base_id(pkey) != EVP_PKEY_RSA) { 246 fido_log_debug("%s: EVP_PKEY_base_id", __func__); 247 goto fail; 248 } 249 250 if ((md = rs256_get_EVP_MD()) == NULL) { 251 fido_log_debug("%s: rs256_get_EVP_MD", __func__); 252 goto fail; 253 } 254 255 if ((pctx = EVP_PKEY_CTX_new(pkey, NULL)) == NULL || 256 EVP_PKEY_verify_init(pctx) != 1 || 257 EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PADDING) != 1 || 258 EVP_PKEY_CTX_set_signature_md(pctx, md) != 1) { 259 fido_log_debug("%s: EVP_PKEY_CTX", __func__); 260 goto fail; 261 } 262 263 if (EVP_PKEY_verify(pctx, sig->ptr, sig->len, dgst->ptr, 264 dgst->len) != 1) { 265 fido_log_debug("%s: EVP_PKEY_verify", __func__); 266 goto fail; 267 } 268 269 ok = 0; 270 fail: 271 EVP_PKEY_CTX_free(pctx); 272 rs256_free_EVP_MD(md); 273 274 return (ok); 275 } 276 277 int 278 rs256_pk_verify_sig(const fido_blob_t *dgst, const rs256_pk_t *pk, 279 const fido_blob_t *sig) 280 { 281 EVP_PKEY *pkey; 282 int ok = -1; 283 284 if ((pkey = rs256_pk_to_EVP_PKEY(pk)) == NULL || 285 rs256_verify_sig(dgst, pkey, sig) < 0) { 286 fido_log_debug("%s: rs256_verify_sig", __func__); 287 goto fail; 288 } 289 290 ok = 0; 291 fail: 292 EVP_PKEY_free(pkey); 293 294 return (ok); 295 } 296