21#include <openssl/bio.h>
22#include <openssl/evp.h>
23#include <openssl/pem.h>
24#include <openssl/x509.h>
31 int real_len = BN_num_bytes(
bn);
33 if (real_len > element_len) {
37 memset(in_ptr, 0, (
size_t)(element_len - real_len));
38 in_ptr += element_len - real_len;
39 BN_bn2bin(
bn, in_ptr);
44static unsigned const char sha1oid[] = {0x30, 0x21, 0x30, 0x09, 0x06,
45 0x05, 0x2B, 0x0E, 0x03, 0x02,
46 0x1A, 0x05, 0x00, 0x04, 0x14};
48static unsigned const char sha256oid[] = {0x30, 0x31, 0x30, 0x0D, 0x06,
49 0x09, 0x60, 0x86, 0x48, 0x01,
50 0x65, 0x03, 0x04, 0x02, 0x01,
51 0x05, 0x00, 0x04, 0x20};
53static unsigned const char sha384oid[] = {0x30, 0x41, 0x30, 0x0D, 0x06,
54 0x09, 0x60, 0x86, 0x48, 0x01,
55 0x65, 0x03, 0x04, 0x02, 0x02,
56 0x05, 0x00, 0x04, 0x30};
58static unsigned const char sha512oid[] = {0x30, 0x51, 0x30, 0x0D, 0x06,
59 0x09, 0x60, 0x86, 0x48, 0x01,
60 0x65, 0x03, 0x04, 0x02, 0x03,
61 0x05, 0x00, 0x04, 0x40};
63static unsigned const char PEM_private_header[] =
64 "-----BEGIN PRIVATE KEY-----\n";
65static unsigned const char PEM_private_trailer[] =
66 "-----END PRIVATE KEY-----\n";
67static unsigned const char PEM_public_header[] =
"-----BEGIN PUBLIC KEY-----\n";
68static unsigned const char PEM_public_trailer[] =
"-----END PUBLIC KEY-----\n";
69static unsigned const char ed25519private_oid[] = {0x30, 0x2e, 0x02, 0x01,
70 0x00, 0x30, 0x05, 0x06,
71 0x03, 0x2b, 0x65, 0x70,
72 0x04, 0x22, 0x04, 0x20};
73static unsigned const char ed25519public_oid[] = {0x30, 0x29, 0x30, 0x05,
74 0x06, 0x03, 0x2b, 0x65,
81 size_t decoded_len =
sizeof(decoded);
83 if (memcmp(in, PEM_private_header, 28) != 0 ||
84 memcmp(in +
in_len - 26, PEM_private_trailer, 25) != 0) {
89 BIO *b64 = BIO_new(BIO_f_base64());
90 BIO *bio = BIO_new(BIO_s_mem());
91 BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
94 (void) BIO_write(bio, in + 28,
in_len - 28 - 25);
95 (void) BIO_flush(bio);
96 ret = BIO_read(b64, decoded, decoded_len);
100 if (
ret <= 0 ||
ret != 48) {
104 if (memcmp(decoded, ed25519private_oid,
sizeof(ed25519private_oid)) != 0) {
108 memcpy(out, decoded + 16, 32);
117 uint8_t *bytes,
size_t *bytes_len,
bool internal_repr) {
124 EVP_PKEY *private_key;
126 BIO *bio = BIO_new(BIO_s_mem());
131 (void) BIO_write(bio,
buf,
len);
133 private_key = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL);
135 if (private_key == NULL) {
145 EC_KEY *ec_private = NULL;
147 switch (EVP_PKEY_base_id(private_key)) {
149 rsa = EVP_PKEY_get1_RSA(private_key);
151 int size = RSA_size(rsa);
152 const BIGNUM *bn_n, *bn_e, *bn_p, *bn_q;
158 !(e[0] == 0x01 && e[1] == 0x00 && e[2] == 0x01)) {
164 }
else if (size == 384) {
166 }
else if (size == 512) {
176 if (
set_component(bytes + size / 2, bn_q, size / 2) ==
false) {
180 if (internal_repr ==
true) {
181 const BIGNUM *dmp1, *dmq1, *iqmp;
204 *bytes_len = (size / 2) * 7;
211 ec_private = EVP_PKEY_get1_EC_KEY(private_key);
212 if (ec_private == NULL) {
216 const BIGNUM *
s = EC_KEY_get0_private_key(ec_private);
217 const EC_GROUP *group = EC_KEY_get0_group(ec_private);
218 int curve = EC_GROUP_get_curve_name(group);
221 if (curve == NID_X9_62_prime256v1) {
224 }
else if (curve == NID_secp384r1) {
227 }
else if (curve == NID_secp521r1) {
230 }
else if (curve == NID_secp224r1) {
233#ifdef NID_brainpoolP256r1
234 }
else if (curve == NID_brainpoolP256r1) {
238#ifdef NID_brainpoolP384r1
239 }
else if (curve == NID_brainpoolP384r1) {
243#ifdef NID_brainpoolP512r1
244 }
else if (curve == NID_brainpoolP512r1) {
248 }
else if (curve == NID_secp256k1) {
259 if (internal_repr ==
true) {
260 const EC_POINT *ec_public = EC_KEY_get0_public_key(ec_private);
272 if (EC_POINT_get_affine_coordinates_GFp(group, ec_public, x, y, NULL) ==
287 *bytes_len = size * 3;
316 if (ec_private != NULL) {
317 EC_KEY_free(ec_private);
321 EVP_PKEY_free(private_key);
329 sprintf(str + (2 * i),
"%02x", digest[i]);
338 return NID_X9_62_prime256v1;
341 return NID_secp384r1;
344 return NID_secp521r1;
347 return NID_secp224r1;
350 return NID_secp256k1;
352#ifdef NID_brainpoolP256r1
354 return NID_brainpoolP256r1;
357#ifdef NID_brainpoolP384r1
359 return NID_brainpoolP384r1;
362#ifdef NID_brainpoolP512r1
364 return NID_brainpoolP512r1;
453 int *digestinfo_len) {
454 if (data_len >=
sizeof(sha1oid) &&
455 memcmp(sha1oid, data,
sizeof(sha1oid)) == 0) {
456 *md_type = EVP_sha1();
457 *digestinfo_len =
sizeof(sha1oid);
458 }
else if (data_len >=
sizeof(sha256oid) &&
459 memcmp(sha256oid, data,
sizeof(sha256oid)) == 0) {
460 *md_type = EVP_sha256();
461 *digestinfo_len =
sizeof(sha256oid);
462 }
else if (data_len >=
sizeof(sha384oid) &&
463 memcmp(sha384oid, data,
sizeof(sha384oid)) == 0) {
464 *md_type = EVP_sha384();
465 *digestinfo_len =
sizeof(sha384oid);
466 }
else if (data_len >=
sizeof(sha512oid) &&
467 memcmp(sha512oid, data,
sizeof(sha512oid)) == 0) {
468 *md_type = EVP_sha512();
469 *digestinfo_len =
sizeof(sha512oid);
471 *md_type = EVP_md_null();
478 size_t available = *buf_len;
482 n = fread(
p, 1, available, fp);
485 }
while (!feof(fp) && !ferror(fp) && available > 0);
491 if (!feof(fp) && available == 0) {
493 n = fread(b, 1, 1, fp);
505 BIO *b64 = BIO_new(BIO_f_base64());
506 BIO *bio = BIO_new(BIO_s_mem());
507 BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
510 (void) BIO_write(bio, in, strlen(in));
511 (void) BIO_flush(bio);
512 ret = BIO_read(b64, out, *
len);
526 size_t in_len = strlen(in);
527 if (in[
in_len - 1] ==
'\n') {
530 if (in[
in_len - 1] ==
'\r') {
539 for (
size_t i = 0; i <
in_len / 2; i++) {
546 buf[1] = in[pos + 1];
547 num = strtol((
const char *)
buf, &endptr, 16);
548 if ((errno == ERANGE && (num < 0 || num > UCHAR_MAX)) ||
549 (errno != 0 && num == 0) || *endptr !=
'\0') {
563 size_t length = buf_len;
571 b64 = BIO_new(BIO_f_base64());
572 bio = BIO_new(BIO_s_mem());
573 bio = BIO_push(b64, bio);
575 (void) BIO_set_flags(bio, BIO_FLAGS_BASE64_NO_NL);
576 (void) BIO_write(bio,
buf, buf_len);
577 (void) BIO_flush(bio);
578 (void) BIO_get_mem_ptr(bio, &bufferPtr);
580 length = bufferPtr->length;
582 data = calloc(buf_len * 2 + 1, 1);
586 for (
size_t i = 0; i < buf_len; i++) {
587 sprintf((
char *) data + i * 2,
"%02x",
buf[i]);
590 length = buf_len * 2;
594 written = fwrite(
p, 1, length, fp);
597 }
while (!feof(fp) && !ferror(fp) && length > 0);
599 if (fp == stdout || fp == stderr) {
613 if (ferror(fp) || feof(fp)) {
625 if (b64_encode ==
true) {
630 if ((
buf[0] & 0x80) != 0) {
634 memcpy(asn1, ed25519public_oid,
sizeof(ed25519public_oid));
636 memset(asn1 +
sizeof(ed25519public_oid), 0, padding);
638 memcpy(asn1 +
sizeof(ed25519public_oid) + padding,
buf, buf_len);
642 write_file(asn1,
sizeof(ed25519public_oid) + padding + buf_len, fp,
true);
661 block_size = EVP_MD_block_size(EVP_sha1());
665 block_size = EVP_MD_block_size(EVP_sha256());
669 block_size = EVP_MD_block_size(EVP_sha384());
673 block_size = EVP_MD_block_size(EVP_sha512());
680 if (
in_len > block_size) {
686 for (
uint8_t i = 0; i < block_size; i++) {
687 out[i] = key[i] ^ 0x36;
688 out[i + block_size] = key[i] ^ 0x5c;
#define insecure_memzero(buf, len)
void RSA_get0_crt_params(const RSA *r, const BIGNUM **dmp1, const BIGNUM **dmq1, const BIGNUM **iqmp)
void RSA_get0_key(const RSA *r, const BIGNUM **n, const BIGNUM **e, const BIGNUM **d)
void RSA_get0_factors(const RSA *r, const BIGNUM **p, const BIGNUM **q)
int algo2nid(yh_algorithm algo)
bool read_ed25519_key(uint8_t *in, size_t in_len, uint8_t *out, size_t *out_len)
bool split_hmac_key(yh_algorithm algorithm, uint8_t *in, size_t in_len, uint8_t *out, size_t *out_len)
bool write_ed25519_key(uint8_t *buf, size_t buf_len, FILE *fp, bool b64_encode)
void format_digest(uint8_t *digest, char *str, uint16_t len)
bool algo2type(yh_algorithm algorithm, yh_object_type *type)
bool base64_decode(const char *in, uint8_t *out, size_t *len)
bool set_component(unsigned char *in_ptr, const BIGNUM *bn, int element_len)
bool read_file(FILE *fp, uint8_t *buf, size_t *buf_len)
void parse_NID(uint8_t *data, uint16_t data_len, const EVP_MD **md_type, int *digestinfo_len)
bool write_file(const uint8_t *buf, size_t buf_len, FILE *fp, format_t format)
bool read_private_key(uint8_t *buf, size_t len, yh_algorithm *algo, uint8_t *bytes, size_t *bytes_len, bool internal_repr)
bool hex_decode(const char *in, uint8_t *out, size_t *len)
@ YH_OTP_AEAD_KEY
OTP AEAD Key is a secret key used to decrypt Yubico OTP values.
@ YH_HMAC_KEY
HMAC Key is a secret key used when computing and verifying HMAC signatures.
@ YH_ASYMMETRIC_KEY
Asymmetric Key is the private key of an asymmetric key-pair.
@ YH_AUTHENTICATION_KEY
Authentication Key is used to establish Sessions with a device.
@ YH_ALGO_MGF1_SHA512
mgf1-sha512
@ YH_ALGO_RSA_PSS_SHA384
rsa-pss-sha384
@ YH_ALGO_RSA_PKCS1_SHA256
rsa-pkcs1-sha256
@ YH_ALGO_RSA_PKCS1_SHA1
rsa-pkcs1-sha1
@ YH_ALGO_RSA_PSS_SHA512
rsa-pss-sha512
@ YH_ALGO_EC_BP384
ecbp384
@ YH_ALGO_RSA_PSS_SHA1
rsa-pss-sha1
@ YH_ALGO_EC_ECDSA_SHA256
ecdsa-sha256
@ YH_ALGO_EC_ECDSA_SHA512
ecdsa-sha512
@ YH_ALGO_AES128_YUBICO_AUTHENTICATION
aes128-yubico-authentication
@ YH_ALGO_RSA_OAEP_SHA256
rsa-oaep-sha256
@ YH_ALGO_OPAQUE_X509_CERTIFICATE
opaque-x509-certificate
@ YH_ALGO_AES192_YUBICO_OTP
aes192-yubico-otp
@ YH_ALGO_AES128_YUBICO_OTP
aes128-yubico-otp
@ YH_ALGO_EC_ECDSA_SHA384
ecdsa-sha384
@ YH_ALGO_EC_ED25519
ed25519
@ YH_ALGO_HMAC_SHA512
hmac-sha512
@ YH_ALGO_HMAC_SHA384
hmac-sha384
@ YH_ALGO_MGF1_SHA384
mgf1-sha384
@ YH_ALGO_RSA_PKCS1_SHA512
rsa-pkcs1-sha512
@ YH_ALGO_AES256_CCM_WRAP
aes256-ccm-wrap
@ YH_ALGO_HMAC_SHA1
hmac-sha1
@ YH_ALGO_RSA_OAEP_SHA512
rsa-oaep-sha512
@ YH_ALGO_RSA_2048
rsa2048
@ YH_ALGO_HMAC_SHA256
hmac-sha256
@ YH_ALGO_RSA_OAEP_SHA384
rsa-oaep-sha384
@ YH_ALGO_OPAQUE_DATA
opaque-data
@ YH_ALGO_AES192_CCM_WRAP
aes192-ccm-wrap
@ YH_ALGO_EC_BP512
ecbp512
@ YH_ALGO_EC_BP256
ecbp256
@ YH_ALGO_RSA_PSS_SHA256
rsa-pss-sha256
@ YH_ALGO_AES256_YUBICO_OTP
aes256-yubico-otp
@ YH_ALGO_TEMPLATE_SSH
template-ssh
@ YH_ALGO_MGF1_SHA1
mgf1-sha1
@ YH_ALGO_AES128_CCM_WRAP
aes128-ccm-wrap
@ YH_ALGO_MGF1_SHA256
mgf1-sha256
@ YH_ALGO_RSA_4096
rsa4096
@ YH_ALGO_EC_ECDSA_SHA1
ecdsa-sha1
@ YH_ALGO_RSA_OAEP_SHA1
rsa-oaep-sha1
@ YH_ALGO_RSA_PKCS1_SHA384
rsa-pkcs1-sha384
@ YH_ALGO_RSA_3072
rsa3072
memset(pInfo->slotDescription, ' ', 64)
memcpy((char *) pInfo->slotDescription, s, l)