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