Merge branch 'master' of https://github.com/Jakuje/yubico-piv-tool into Jakuje-master
This commit is contained in:
+1
-1
@@ -40,7 +40,7 @@ noinst_LTLIBRARIES = libpiv_cmd.la libpiv_util.la
|
||||
libpiv_cmd_la_SOURCES = cmdline.ggo cmdline.c cmdline.h
|
||||
libpiv_cmd_la_CFLAGS =
|
||||
|
||||
libpiv_util_la_SOURCES = util.c util.h
|
||||
libpiv_util_la_SOURCES = util.c util.h openssl-compat.c openssl-compat.h
|
||||
libpiv_util_la_LIBADD = $(top_builddir)/lib/libykpiv.la $(OPENSSL_LIBS)
|
||||
|
||||
cmdline.c cmdline.h: cmdline.ggo Makefile.am $(top_srcdir)/configure.ac
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include "openssl-compat.h"
|
||||
#if OPENSSL_VERSION_NUMBER < 0x10100000L
|
||||
|
||||
#include <string.h>
|
||||
#include <openssl/engine.h>
|
||||
|
||||
|
||||
int RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d)
|
||||
{
|
||||
/* If the fields n and e in r are NULL, the corresponding input
|
||||
* parameters MUST be non-NULL for n and e. d may be
|
||||
* left NULL (in case only the public key is used).
|
||||
*/
|
||||
if ((r->n == NULL && n == NULL)
|
||||
|| (r->e == NULL && e == NULL))
|
||||
return 0;
|
||||
|
||||
if (n != NULL) {
|
||||
BN_free(r->n);
|
||||
r->n = n;
|
||||
}
|
||||
if (e != NULL) {
|
||||
BN_free(r->e);
|
||||
r->e = e;
|
||||
}
|
||||
if (d != NULL) {
|
||||
BN_free(r->d);
|
||||
r->d = d;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void RSA_get0_key(const RSA *r,
|
||||
const BIGNUM **n, const BIGNUM **e, const BIGNUM **d)
|
||||
{
|
||||
if (n != NULL)
|
||||
*n = r->n;
|
||||
if (e != NULL)
|
||||
*e = r->e;
|
||||
if (d != NULL)
|
||||
*d = r->d;
|
||||
}
|
||||
|
||||
void RSA_get0_factors(const RSA *r, const BIGNUM **p, const BIGNUM **q)
|
||||
{
|
||||
if (p != NULL)
|
||||
*p = r->p;
|
||||
if (q != NULL)
|
||||
*q = r->q;
|
||||
}
|
||||
|
||||
void RSA_get0_crt_params(const RSA *r,
|
||||
const BIGNUM **dmp1, const BIGNUM **dmq1,
|
||||
const BIGNUM **iqmp)
|
||||
{
|
||||
if (dmp1 != NULL)
|
||||
*dmp1 = r->dmp1;
|
||||
if (dmq1 != NULL)
|
||||
*dmq1 = r->dmq1;
|
||||
if (iqmp != NULL)
|
||||
*iqmp = r->iqmp;
|
||||
}
|
||||
|
||||
void X509_SIG_getm(X509_SIG *sig, X509_ALGOR **palg,
|
||||
ASN1_OCTET_STRING **pdigest)
|
||||
{
|
||||
if (palg)
|
||||
*palg = sig->algor;
|
||||
if (pdigest)
|
||||
*pdigest = sig->digest;
|
||||
}
|
||||
|
||||
#endif /* OPENSSL_VERSION_NUMBER */
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the OpenSSL license (the "License"). You may not use
|
||||
* this file except in compliance with the License. You can obtain a copy
|
||||
* in the file LICENSE in the source distribution or at
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#ifndef LIBCRYPTO_COMPAT_H
|
||||
#define LIBCRYPTO_COMPAT_H
|
||||
|
||||
#include <openssl/opensslv.h>
|
||||
#if OPENSSL_VERSION_NUMBER < 0x10100000L
|
||||
|
||||
#include <openssl/rsa.h>
|
||||
#include <openssl/dsa.h>
|
||||
#include <openssl/ecdsa.h>
|
||||
#include <openssl/dh.h>
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/x509.h>
|
||||
|
||||
int RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d);
|
||||
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);
|
||||
void RSA_get0_crt_params(const RSA *r,
|
||||
const BIGNUM **dmp1, const BIGNUM **dmq1,
|
||||
const BIGNUM **iqmp);
|
||||
void X509_SIG_getm(X509_SIG *sig, X509_ALGOR **palg,
|
||||
ASN1_OCTET_STRING **pdigest);
|
||||
|
||||
#endif /* OPENSSL_VERSION_NUMBER */
|
||||
#endif /* LIBCRYPTO_COMPAT_H */
|
||||
|
||||
+19
-16
@@ -37,6 +37,7 @@
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#include "openssl-compat.h"
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/x509.h>
|
||||
#include <openssl/rsa.h>
|
||||
@@ -80,7 +81,7 @@ FILE *open_file(const char *file_name, enum file_mode mode) {
|
||||
}
|
||||
|
||||
unsigned char get_algorithm(EVP_PKEY *key) {
|
||||
int type = EVP_PKEY_type(key->type);
|
||||
int type = EVP_PKEY_type(EVP_PKEY_id(key));
|
||||
switch(type) {
|
||||
case EVP_PKEY_RSA:
|
||||
{
|
||||
@@ -333,23 +334,23 @@ bool set_component(unsigned char *in_ptr, const BIGNUM *bn, int element_len) {
|
||||
}
|
||||
|
||||
bool prepare_rsa_signature(const unsigned char *in, unsigned int in_len, unsigned char *out, unsigned int *out_len, int nid) {
|
||||
X509_SIG digestInfo;
|
||||
X509_ALGOR algor;
|
||||
X509_SIG *digestInfo;
|
||||
X509_ALGOR *algor;
|
||||
ASN1_TYPE parameter;
|
||||
ASN1_OCTET_STRING digest;
|
||||
ASN1_OCTET_STRING *digest;
|
||||
unsigned char data[1024];
|
||||
|
||||
memcpy(data, in, in_len);
|
||||
|
||||
digestInfo.algor = &algor;
|
||||
digestInfo.algor->algorithm = OBJ_nid2obj(nid);
|
||||
digestInfo.algor->parameter = ¶meter;
|
||||
digestInfo.algor->parameter->type = V_ASN1_NULL;
|
||||
digestInfo.algor->parameter->value.ptr = NULL;
|
||||
digestInfo.digest = &digest;
|
||||
digestInfo.digest->data = data;
|
||||
digestInfo.digest->length = (int)in_len;
|
||||
*out_len = (unsigned int)i2d_X509_SIG(&digestInfo, &out);
|
||||
digestInfo = X509_SIG_new();
|
||||
X509_SIG_getm(digestInfo, &algor, &digest);
|
||||
algor = X509_ALGOR_new();
|
||||
X509_ALGOR_set0(algor, OBJ_nid2obj(nid), V_ASN1_NULL, ¶meter);
|
||||
parameter.type = V_ASN1_NULL;
|
||||
parameter.value.ptr = NULL;
|
||||
digest->data = data;
|
||||
digest->length = (int)in_len;
|
||||
*out_len = (unsigned int)i2d_X509_SIG(digestInfo, &out);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -532,22 +533,24 @@ int SSH_write_X509(FILE *fp, X509 *x) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
switch (pkey->type) {
|
||||
switch (EVP_PKEY_id(pkey)) {
|
||||
case EVP_PKEY_RSA:
|
||||
case EVP_PKEY_RSA2: {
|
||||
RSA *rsa;
|
||||
unsigned char n[256];
|
||||
const BIGNUM *bn_n;
|
||||
|
||||
char rsa_id[] = "\x00\x00\x00\x07ssh-rsa";
|
||||
char rsa_f4[] = "\x00\x00\x00\x03\x01\x00\x01";
|
||||
|
||||
rsa = EVP_PKEY_get1_RSA(pkey);
|
||||
RSA_get0_key(rsa, &bn_n, NULL, NULL);
|
||||
|
||||
if (!set_component(n, rsa->n, RSA_size(rsa))) {
|
||||
if (!set_component(n, bn_n, RSA_size(rsa))) {
|
||||
break;
|
||||
}
|
||||
|
||||
uint32_t bytes = BN_num_bytes(rsa->n);
|
||||
uint32_t bytes = BN_num_bytes(bn_n);
|
||||
char len_buf[5];
|
||||
int len = 4;
|
||||
|
||||
|
||||
+88
-8
@@ -42,6 +42,7 @@
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#include "openssl-compat.h"
|
||||
#include <openssl/des.h>
|
||||
#include <openssl/pem.h>
|
||||
#include <openssl/pkcs12.h>
|
||||
@@ -123,6 +124,58 @@ static bool sign_data(ykpiv_state *state, const unsigned char *in, size_t len, u
|
||||
return false;
|
||||
}
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
|
||||
static int ec_key_ex_data_idx = -1;
|
||||
|
||||
struct internal_key {
|
||||
ykpiv_state *state;
|
||||
int algorithm;
|
||||
int key;
|
||||
};
|
||||
|
||||
int yk_rsa_meth_sign(int dtype, const unsigned char *m, unsigned int m_length,
|
||||
unsigned char *sigret, unsigned int *siglen, const RSA *rsa) {
|
||||
const RSA_METHOD *meth = RSA_get_method(rsa);
|
||||
const struct internal_key *key = RSA_meth_get0_app_data(meth);
|
||||
if (sign_data(key->state, m, m_length, sigret, (size_t *)siglen, key->algorithm, key->key))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int yk_ec_meth_sign(int type, const unsigned char *dgst, int dlen,
|
||||
unsigned char *sig, unsigned int *siglen, const BIGNUM *kinv,
|
||||
const BIGNUM *r, EC_KEY *ec) {
|
||||
const struct internal_key *key = EC_KEY_get_ex_data(ec, ec_key_ex_data_idx);
|
||||
if (sign_data(key->state, dgst, dlen, sig, (size_t *)siglen, key->algorithm, key->key))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int wrap_public_key(ykpiv_state *state, int algorithm, EVP_PKEY *public_key,
|
||||
int key) {
|
||||
if(YKPIV_IS_RSA(algorithm)) {
|
||||
RSA_METHOD *meth = RSA_meth_dup(RSA_get_default_method());
|
||||
RSA *rsa = EVP_PKEY_get0_RSA(public_key);
|
||||
struct internal_key int_key = {state, algorithm, key};
|
||||
RSA_meth_set0_app_data(meth, &int_key);
|
||||
RSA_meth_set_sign(meth, yk_rsa_meth_sign);
|
||||
RSA_set_method(rsa, meth);
|
||||
} else {
|
||||
EC_KEY *ec = EVP_PKEY_get0_EC_KEY(public_key);
|
||||
EC_KEY_METHOD *meth = EC_KEY_METHOD_new(EC_KEY_get_method(ec));
|
||||
struct internal_key int_key = {state, algorithm, key};
|
||||
if (ec_key_ex_data_idx == -1)
|
||||
ec_key_ex_data_idx = EC_KEY_get_ex_new_index(0, NULL, NULL, NULL, 0);
|
||||
EC_KEY_set_ex_data(ec, ec_key_ex_data_idx, &int_key);
|
||||
EC_KEY_METHOD_set_sign(meth, yk_ec_meth_sign, NULL, NULL); /* XXX ?? */
|
||||
EC_KEY_set_method(ec, meth);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static bool generate_key(ykpiv_state *state, enum enum_slot slot,
|
||||
enum enum_algorithm algorithm, const char *output_file_name,
|
||||
enum enum_key_format key_format, enum enum_pin_policy pin_policy,
|
||||
@@ -179,6 +232,8 @@ static bool generate_key(ykpiv_state *state, enum enum_slot slot,
|
||||
fprintf(stderr, "Failed to parse public key exponent.\n");
|
||||
goto generate_out;
|
||||
}
|
||||
|
||||
RSA_set0_key(rsa, bignum_n, bignum_e, NULL);
|
||||
EVP_PKEY_set1_RSA(public_key, rsa);
|
||||
} else if(algorithm == algorithm_arg_ECCP256 || algorithm == algorithm_arg_ECCP384) {
|
||||
EC_GROUP *group;
|
||||
@@ -329,39 +384,43 @@ static bool import_key(ykpiv_state *state, enum enum_key_format key_format,
|
||||
unsigned char dmp1[128];
|
||||
unsigned char dmq1[128];
|
||||
unsigned char iqmp[128];
|
||||
const BIGNUM *bn_e, *bn_p, *bn_q, *bn_dmp1, *bn_dmq1, *bn_iqmp;
|
||||
|
||||
int element_len = 128;
|
||||
if(algorithm == YKPIV_ALGO_RSA1024) {
|
||||
element_len = 64;
|
||||
}
|
||||
|
||||
if((set_component(e, rsa_private_key->e, 3) == false) ||
|
||||
RSA_get0_key(rsa_private_key, NULL, &bn_e, NULL);
|
||||
RSA_get0_factors(rsa_private_key, &bn_p, &bn_q);
|
||||
RSA_get0_crt_params(rsa_private_key, &bn_dmp1, &bn_dmq1, &bn_iqmp);
|
||||
if((set_component(e, bn_e, 3) == false) ||
|
||||
!(e[0] == 0x01 && e[1] == 0x00 && e[2] == 0x01)) {
|
||||
fprintf(stderr, "Invalid public exponent for import (only 0x10001 supported)\n");
|
||||
goto import_out;
|
||||
}
|
||||
|
||||
if(set_component(p, rsa_private_key->p, element_len) == false) {
|
||||
if(set_component(p, bn_p, element_len) == false) {
|
||||
fprintf(stderr, "Failed setting p component.\n");
|
||||
goto import_out;
|
||||
}
|
||||
|
||||
if(set_component(q, rsa_private_key->q, element_len) == false) {
|
||||
if(set_component(q, bn_q, element_len) == false) {
|
||||
fprintf(stderr, "Failed setting q component.\n");
|
||||
goto import_out;
|
||||
}
|
||||
|
||||
if(set_component(dmp1, rsa_private_key->dmp1, element_len) == false) {
|
||||
if(set_component(dmp1, bn_dmp1, element_len) == false) {
|
||||
fprintf(stderr, "Failed setting dmp1 component.\n");
|
||||
goto import_out;
|
||||
}
|
||||
|
||||
if(set_component(dmq1, rsa_private_key->dmq1, element_len) == false) {
|
||||
if(set_component(dmq1, bn_dmq1, element_len) == false) {
|
||||
fprintf(stderr, "Failed setting dmq1 component.\n");
|
||||
goto import_out;
|
||||
}
|
||||
|
||||
if(set_component(iqmp, rsa_private_key->iqmp, element_len) == false) {
|
||||
if(set_component(iqmp, bn_iqmp, element_len) == false) {
|
||||
fprintf(stderr, "Failed setting iqmp component.\n");
|
||||
goto import_out;
|
||||
}
|
||||
@@ -627,6 +686,7 @@ static bool request_certificate(ykpiv_state *state, enum enum_key_format key_for
|
||||
goto request_out;
|
||||
}
|
||||
|
||||
#if OPENSSL_VERSION_NUMBER < 0x10100000L
|
||||
memcpy(digest, oid, oid_len);
|
||||
/* XXX: this should probably use X509_REQ_digest() but that's buggy */
|
||||
if(!ASN1_item_digest(ASN1_ITEM_rptr(X509_REQ_INFO), md, req->req_info,
|
||||
@@ -640,6 +700,7 @@ static bool request_certificate(ykpiv_state *state, enum enum_key_format key_for
|
||||
fprintf(stderr, "Unsupported algorithm %x or hash %x\n", algorithm, hash);
|
||||
goto request_out;
|
||||
}
|
||||
|
||||
if(YKPIV_IS_RSA(algorithm)) {
|
||||
signinput = digest;
|
||||
len = oid_len + digest_len;
|
||||
@@ -662,6 +723,13 @@ static bool request_certificate(ykpiv_state *state, enum enum_key_format key_for
|
||||
/* mark that all bits should be used. */
|
||||
req->signature->flags = ASN1_STRING_FLAG_BITS_LEFT;
|
||||
}
|
||||
#else
|
||||
/* With opaque structures we can not touch whatever we want, but we need
|
||||
* to embed the sign_data function in the RSA/EC key structures */
|
||||
wrap_public_key(state, algorithm, public_key, key);
|
||||
|
||||
X509_REQ_sign(req, public_key, md);
|
||||
#endif
|
||||
|
||||
if(key_format == key_format_arg_PEM) {
|
||||
PEM_write_X509_REQ(output_file, req);
|
||||
@@ -681,9 +749,11 @@ request_out:
|
||||
EVP_PKEY_free(public_key);
|
||||
}
|
||||
if(req) {
|
||||
#if OPENSSL_VERSION_NUMBER < 0x10100000L
|
||||
if(req->sig_alg->parameter) {
|
||||
req->sig_alg->parameter = NULL;
|
||||
}
|
||||
#endif
|
||||
X509_REQ_free(req);
|
||||
}
|
||||
if(name) {
|
||||
@@ -812,6 +882,7 @@ static bool selfsign_certificate(ykpiv_state *state, enum enum_key_format key_fo
|
||||
if(nid == 0) {
|
||||
goto selfsign_out;
|
||||
}
|
||||
#if OPENSSL_VERSION_NUMBER < 0x10100000L
|
||||
if(YKPIV_IS_RSA(algorithm)) {
|
||||
signinput = digest;
|
||||
len = oid_len + md_len;
|
||||
@@ -845,6 +916,13 @@ static bool selfsign_certificate(ykpiv_state *state, enum enum_key_format key_fo
|
||||
* certificate can be validated. */
|
||||
x509->signature->flags = ASN1_STRING_FLAG_BITS_LEFT;
|
||||
}
|
||||
#else
|
||||
/* With opaque structures we can not touch whatever we want, but we need
|
||||
* to embed the sign_data function in the RSA/EC key structures */
|
||||
wrap_public_key(state, algorithm, public_key, key);
|
||||
|
||||
X509_sign(x509, public_key, md);
|
||||
#endif
|
||||
|
||||
if(key_format == key_format_arg_PEM) {
|
||||
PEM_write_X509(output_file, x509);
|
||||
@@ -861,10 +939,12 @@ selfsign_out:
|
||||
fclose(output_file);
|
||||
}
|
||||
if(x509) {
|
||||
#if OPENSSL_VERSION_NUMBER < 0x10100000L
|
||||
if(x509->sig_alg->parameter) {
|
||||
x509->sig_alg->parameter = NULL;
|
||||
x509->cert_info->signature->parameter = NULL;
|
||||
}
|
||||
#endif
|
||||
X509_free(x509);
|
||||
}
|
||||
if(public_key) {
|
||||
@@ -1325,7 +1405,7 @@ static bool test_signature(ykpiv_state *state, enum enum_slot slot,
|
||||
{
|
||||
unsigned char rand[128];
|
||||
EVP_MD_CTX *mdctx;
|
||||
if(RAND_pseudo_bytes(rand, 128) == -1) {
|
||||
if(RAND_bytes(rand, 128) == -1) {
|
||||
fprintf(stderr, "error: no randomness.\n");
|
||||
return false;
|
||||
}
|
||||
@@ -1472,7 +1552,7 @@ static bool test_decipher(ykpiv_state *state, enum enum_slot slot,
|
||||
size_t len2 = sizeof(data);
|
||||
RSA *rsa = EVP_PKEY_get1_RSA(pubkey);
|
||||
|
||||
if(RAND_pseudo_bytes(secret, sizeof(secret)) == -1) {
|
||||
if(RAND_bytes(secret, sizeof(secret)) == -1) {
|
||||
fprintf(stderr, "error: no randomness.\n");
|
||||
ret = false;
|
||||
goto decipher_out;
|
||||
|
||||
Reference in New Issue
Block a user