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/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 < 0x10100000L 15 static int 16 RSA_bits(const RSA *r) 17 { 18 return (BN_num_bits(r->n)); 19 } 20 21 static int 22 RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d) 23 { 24 r->n = n; 25 r->e = e; 26 r->d = d; 27 28 return (1); 29 } 30 31 static void 32 RSA_get0_key(const RSA *r, const BIGNUM **n, const BIGNUM **e, const BIGNUM **d) 33 { 34 *n = r->n; 35 *e = r->e; 36 *d = r->d; 37 } 38 #endif /* OPENSSL_VERSION_NUMBER < 0x10100000L */ 39 40 static int 41 decode_bignum(const cbor_item_t *item, void *ptr, size_t len) 42 { 43 if (cbor_isa_bytestring(item) == false || 44 cbor_bytestring_is_definite(item) == false || 45 cbor_bytestring_length(item) != len) { 46 fido_log_debug("%s: cbor type", __func__); 47 return (-1); 48 } 49 50 memcpy(ptr, cbor_bytestring_handle(item), len); 51 52 return (0); 53 } 54 55 static int 56 decode_rsa_pubkey(const cbor_item_t *key, const cbor_item_t *val, void *arg) 57 { 58 rs256_pk_t *k = arg; 59 60 if (cbor_isa_negint(key) == false || 61 cbor_int_get_width(key) != CBOR_INT_8) 62 return (0); /* ignore */ 63 64 switch (cbor_get_uint8(key)) { 65 case 0: /* modulus */ 66 return (decode_bignum(val, &k->n, sizeof(k->n))); 67 case 1: /* public exponent */ 68 return (decode_bignum(val, &k->e, sizeof(k->e))); 69 } 70 71 return (0); /* ignore */ 72 } 73 74 int 75 rs256_pk_decode(const cbor_item_t *item, rs256_pk_t *k) 76 { 77 if (cbor_isa_map(item) == false || 78 cbor_map_is_definite(item) == false || 79 cbor_map_iter(item, k, decode_rsa_pubkey) < 0) { 80 fido_log_debug("%s: cbor type", __func__); 81 return (-1); 82 } 83 84 return (0); 85 } 86 87 rs256_pk_t * 88 rs256_pk_new(void) 89 { 90 return (calloc(1, sizeof(rs256_pk_t))); 91 } 92 93 void 94 rs256_pk_free(rs256_pk_t **pkp) 95 { 96 rs256_pk_t *pk; 97 98 if (pkp == NULL || (pk = *pkp) == NULL) 99 return; 100 101 freezero(pk, sizeof(*pk)); 102 *pkp = NULL; 103 } 104 105 int 106 rs256_pk_from_ptr(rs256_pk_t *pk, const void *ptr, size_t len) 107 { 108 if (len < sizeof(*pk)) 109 return (FIDO_ERR_INVALID_ARGUMENT); 110 111 memcpy(pk, ptr, sizeof(*pk)); 112 113 return (FIDO_OK); 114 } 115 116 EVP_PKEY * 117 rs256_pk_to_EVP_PKEY(const rs256_pk_t *k) 118 { 119 RSA *rsa = NULL; 120 EVP_PKEY *pkey = NULL; 121 BIGNUM *n = NULL; 122 BIGNUM *e = NULL; 123 int ok = -1; 124 125 if ((n = BN_new()) == NULL || (e = BN_new()) == NULL) 126 goto fail; 127 128 if (BN_bin2bn(k->n, sizeof(k->n), n) == NULL || 129 BN_bin2bn(k->e, sizeof(k->e), e) == NULL) { 130 fido_log_debug("%s: BN_bin2bn", __func__); 131 goto fail; 132 } 133 134 if ((rsa = RSA_new()) == NULL || RSA_set0_key(rsa, n, e, NULL) == 0) { 135 fido_log_debug("%s: RSA_set0_key", __func__); 136 goto fail; 137 } 138 139 /* at this point, n and e belong to rsa */ 140 n = NULL; 141 e = NULL; 142 143 if ((pkey = EVP_PKEY_new()) == NULL || 144 EVP_PKEY_assign_RSA(pkey, rsa) == 0) { 145 fido_log_debug("%s: EVP_PKEY_assign_RSA", __func__); 146 goto fail; 147 } 148 149 rsa = NULL; /* at this point, rsa belongs to evp */ 150 151 ok = 0; 152 fail: 153 if (n != NULL) 154 BN_free(n); 155 if (e != NULL) 156 BN_free(e); 157 if (rsa != NULL) 158 RSA_free(rsa); 159 if (ok < 0 && pkey != NULL) { 160 EVP_PKEY_free(pkey); 161 pkey = NULL; 162 } 163 164 return (pkey); 165 } 166 167 int 168 rs256_pk_from_RSA(rs256_pk_t *pk, const RSA *rsa) 169 { 170 const BIGNUM *n = NULL; 171 const BIGNUM *e = NULL; 172 const BIGNUM *d = NULL; 173 int k; 174 175 if (RSA_bits(rsa) != 2048) { 176 fido_log_debug("%s: invalid key length", __func__); 177 return (FIDO_ERR_INVALID_ARGUMENT); 178 } 179 180 RSA_get0_key(rsa, &n, &e, &d); 181 182 if (n == NULL || e == NULL) { 183 fido_log_debug("%s: RSA_get0_key", __func__); 184 return (FIDO_ERR_INTERNAL); 185 } 186 187 if ((k = BN_num_bytes(n)) < 0 || (size_t)k > sizeof(pk->n) || 188 (k = BN_num_bytes(e)) < 0 || (size_t)k > sizeof(pk->e)) { 189 fido_log_debug("%s: invalid key", __func__); 190 return (FIDO_ERR_INTERNAL); 191 } 192 193 if ((k = BN_bn2bin(n, pk->n)) < 0 || (size_t)k > sizeof(pk->n) || 194 (k = BN_bn2bin(e, pk->e)) < 0 || (size_t)k > sizeof(pk->e)) { 195 fido_log_debug("%s: BN_bn2bin", __func__); 196 return (FIDO_ERR_INTERNAL); 197 } 198 199 return (FIDO_OK); 200 } 201