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