Merge branch 'master' of https://github.com/Jakuje/yubico-piv-tool into Jakuje-master

This commit is contained in:
Trevor Bentley
2017-11-20 14:03:48 +01:00
7 changed files with 292 additions and 42 deletions
+1 -1
View File
@@ -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_SOURCES = cmdline.ggo cmdline.c cmdline.h
libpiv_cmd_la_CFLAGS = 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) libpiv_util_la_LIBADD = $(top_builddir)/lib/libykpiv.la $(OPENSSL_LIBS)
cmdline.c cmdline.h: cmdline.ggo Makefile.am $(top_srcdir)/configure.ac cmdline.c cmdline.h: cmdline.ggo Makefile.am $(top_srcdir)/configure.ac
+83
View File
@@ -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 */
+35
View File
@@ -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
View File
@@ -37,6 +37,7 @@
#include <windows.h> #include <windows.h>
#endif #endif
#include "openssl-compat.h"
#include <openssl/evp.h> #include <openssl/evp.h>
#include <openssl/x509.h> #include <openssl/x509.h>
#include <openssl/rsa.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) { 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) { switch(type) {
case EVP_PKEY_RSA: 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) { 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_SIG *digestInfo;
X509_ALGOR algor; X509_ALGOR *algor;
ASN1_TYPE parameter; ASN1_TYPE parameter;
ASN1_OCTET_STRING digest; ASN1_OCTET_STRING *digest;
unsigned char data[1024]; unsigned char data[1024];
memcpy(data, in, in_len); memcpy(data, in, in_len);
digestInfo.algor = &algor; digestInfo = X509_SIG_new();
digestInfo.algor->algorithm = OBJ_nid2obj(nid); X509_SIG_getm(digestInfo, &algor, &digest);
digestInfo.algor->parameter = &parameter; algor = X509_ALGOR_new();
digestInfo.algor->parameter->type = V_ASN1_NULL; X509_ALGOR_set0(algor, OBJ_nid2obj(nid), V_ASN1_NULL, &parameter);
digestInfo.algor->parameter->value.ptr = NULL; parameter.type = V_ASN1_NULL;
digestInfo.digest = &digest; parameter.value.ptr = NULL;
digestInfo.digest->data = data; digest->data = data;
digestInfo.digest->length = (int)in_len; digest->length = (int)in_len;
*out_len = (unsigned int)i2d_X509_SIG(&digestInfo, &out); *out_len = (unsigned int)i2d_X509_SIG(digestInfo, &out);
return true; return true;
} }
@@ -532,22 +533,24 @@ int SSH_write_X509(FILE *fp, X509 *x) {
return ret; return ret;
} }
switch (pkey->type) { switch (EVP_PKEY_id(pkey)) {
case EVP_PKEY_RSA: case EVP_PKEY_RSA:
case EVP_PKEY_RSA2: { case EVP_PKEY_RSA2: {
RSA *rsa; RSA *rsa;
unsigned char n[256]; unsigned char n[256];
const BIGNUM *bn_n;
char rsa_id[] = "\x00\x00\x00\x07ssh-rsa"; char rsa_id[] = "\x00\x00\x00\x07ssh-rsa";
char rsa_f4[] = "\x00\x00\x00\x03\x01\x00\x01"; char rsa_f4[] = "\x00\x00\x00\x03\x01\x00\x01";
rsa = EVP_PKEY_get1_RSA(pkey); 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; break;
} }
uint32_t bytes = BN_num_bytes(rsa->n); uint32_t bytes = BN_num_bytes(bn_n);
char len_buf[5]; char len_buf[5];
int len = 4; int len = 4;
+88 -8
View File
@@ -42,6 +42,7 @@
#include <windows.h> #include <windows.h>
#endif #endif
#include "openssl-compat.h"
#include <openssl/des.h> #include <openssl/des.h>
#include <openssl/pem.h> #include <openssl/pem.h>
#include <openssl/pkcs12.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; 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, static bool generate_key(ykpiv_state *state, enum enum_slot slot,
enum enum_algorithm algorithm, const char *output_file_name, enum enum_algorithm algorithm, const char *output_file_name,
enum enum_key_format key_format, enum enum_pin_policy pin_policy, 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"); fprintf(stderr, "Failed to parse public key exponent.\n");
goto generate_out; goto generate_out;
} }
RSA_set0_key(rsa, bignum_n, bignum_e, NULL);
EVP_PKEY_set1_RSA(public_key, rsa); EVP_PKEY_set1_RSA(public_key, rsa);
} else if(algorithm == algorithm_arg_ECCP256 || algorithm == algorithm_arg_ECCP384) { } else if(algorithm == algorithm_arg_ECCP256 || algorithm == algorithm_arg_ECCP384) {
EC_GROUP *group; 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 dmp1[128];
unsigned char dmq1[128]; unsigned char dmq1[128];
unsigned char iqmp[128]; unsigned char iqmp[128];
const BIGNUM *bn_e, *bn_p, *bn_q, *bn_dmp1, *bn_dmq1, *bn_iqmp;
int element_len = 128; int element_len = 128;
if(algorithm == YKPIV_ALGO_RSA1024) { if(algorithm == YKPIV_ALGO_RSA1024) {
element_len = 64; 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)) { !(e[0] == 0x01 && e[1] == 0x00 && e[2] == 0x01)) {
fprintf(stderr, "Invalid public exponent for import (only 0x10001 supported)\n"); fprintf(stderr, "Invalid public exponent for import (only 0x10001 supported)\n");
goto import_out; 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"); fprintf(stderr, "Failed setting p component.\n");
goto import_out; 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"); fprintf(stderr, "Failed setting q component.\n");
goto import_out; 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"); fprintf(stderr, "Failed setting dmp1 component.\n");
goto import_out; 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"); fprintf(stderr, "Failed setting dmq1 component.\n");
goto import_out; 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"); fprintf(stderr, "Failed setting iqmp component.\n");
goto import_out; goto import_out;
} }
@@ -627,6 +686,7 @@ static bool request_certificate(ykpiv_state *state, enum enum_key_format key_for
goto request_out; goto request_out;
} }
#if OPENSSL_VERSION_NUMBER < 0x10100000L
memcpy(digest, oid, oid_len); memcpy(digest, oid, oid_len);
/* XXX: this should probably use X509_REQ_digest() but that's buggy */ /* 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, 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); fprintf(stderr, "Unsupported algorithm %x or hash %x\n", algorithm, hash);
goto request_out; goto request_out;
} }
if(YKPIV_IS_RSA(algorithm)) { if(YKPIV_IS_RSA(algorithm)) {
signinput = digest; signinput = digest;
len = oid_len + digest_len; 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. */ /* mark that all bits should be used. */
req->signature->flags = ASN1_STRING_FLAG_BITS_LEFT; 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) { if(key_format == key_format_arg_PEM) {
PEM_write_X509_REQ(output_file, req); PEM_write_X509_REQ(output_file, req);
@@ -681,9 +749,11 @@ request_out:
EVP_PKEY_free(public_key); EVP_PKEY_free(public_key);
} }
if(req) { if(req) {
#if OPENSSL_VERSION_NUMBER < 0x10100000L
if(req->sig_alg->parameter) { if(req->sig_alg->parameter) {
req->sig_alg->parameter = NULL; req->sig_alg->parameter = NULL;
} }
#endif
X509_REQ_free(req); X509_REQ_free(req);
} }
if(name) { if(name) {
@@ -812,6 +882,7 @@ static bool selfsign_certificate(ykpiv_state *state, enum enum_key_format key_fo
if(nid == 0) { if(nid == 0) {
goto selfsign_out; goto selfsign_out;
} }
#if OPENSSL_VERSION_NUMBER < 0x10100000L
if(YKPIV_IS_RSA(algorithm)) { if(YKPIV_IS_RSA(algorithm)) {
signinput = digest; signinput = digest;
len = oid_len + md_len; 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. */ * certificate can be validated. */
x509->signature->flags = ASN1_STRING_FLAG_BITS_LEFT; 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) { if(key_format == key_format_arg_PEM) {
PEM_write_X509(output_file, x509); PEM_write_X509(output_file, x509);
@@ -861,10 +939,12 @@ selfsign_out:
fclose(output_file); fclose(output_file);
} }
if(x509) { if(x509) {
#if OPENSSL_VERSION_NUMBER < 0x10100000L
if(x509->sig_alg->parameter) { if(x509->sig_alg->parameter) {
x509->sig_alg->parameter = NULL; x509->sig_alg->parameter = NULL;
x509->cert_info->signature->parameter = NULL; x509->cert_info->signature->parameter = NULL;
} }
#endif
X509_free(x509); X509_free(x509);
} }
if(public_key) { if(public_key) {
@@ -1325,7 +1405,7 @@ static bool test_signature(ykpiv_state *state, enum enum_slot slot,
{ {
unsigned char rand[128]; unsigned char rand[128];
EVP_MD_CTX *mdctx; EVP_MD_CTX *mdctx;
if(RAND_pseudo_bytes(rand, 128) == -1) { if(RAND_bytes(rand, 128) == -1) {
fprintf(stderr, "error: no randomness.\n"); fprintf(stderr, "error: no randomness.\n");
return false; return false;
} }
@@ -1472,7 +1552,7 @@ static bool test_decipher(ykpiv_state *state, enum enum_slot slot,
size_t len2 = sizeof(data); size_t len2 = sizeof(data);
RSA *rsa = EVP_PKEY_get1_RSA(pubkey); 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"); fprintf(stderr, "error: no randomness.\n");
ret = false; ret = false;
goto decipher_out; goto decipher_out;
+21 -10
View File
@@ -31,6 +31,7 @@
#include "openssl_utils.h" #include "openssl_utils.h"
#include <stdbool.h> #include <stdbool.h>
#include "../tool/util.h" // TODO: share this better? #include "../tool/util.h" // TODO: share this better?
#include "../tool/openssl-compat.h" // TODO: share this better?
#include "debug.h" #include "debug.h"
#include <string.h> #include <string.h>
@@ -115,8 +116,7 @@ CK_RV do_create_empty_cert(CK_BYTE_PTR in, CK_ULONG in_len, CK_BBOOL is_rsa,
if(bignum_e == NULL) if(bignum_e == NULL)
goto create_empty_cert_cleanup; goto create_empty_cert_cleanup;
rsa->n = bignum_n; RSA_set0_key(rsa, bignum_n, bignum_e, NULL);
rsa->e = bignum_e;
if (EVP_PKEY_set1_RSA(key, rsa) == 0) if (EVP_PKEY_set1_RSA(key, rsa) == 0)
goto create_empty_cert_cleanup; goto create_empty_cert_cleanup;
@@ -165,6 +165,7 @@ CK_RV do_create_empty_cert(CK_BYTE_PTR in, CK_ULONG in_len, CK_BBOOL is_rsa,
X509_set_notBefore(cert, tm); X509_set_notBefore(cert, tm);
X509_set_notAfter(cert, tm); X509_set_notAfter(cert, tm);
#if OPENSSL_VERSION_NUMBER < 10100000L
// Manually set the signature algorithms. // Manually set the signature algorithms.
// OpenSSL 1.0.1i complains about empty DER fields // OpenSSL 1.0.1i complains about empty DER fields
// 8 => md5WithRsaEncryption // 8 => md5WithRsaEncryption
@@ -174,6 +175,8 @@ CK_RV do_create_empty_cert(CK_BYTE_PTR in, CK_ULONG in_len, CK_BBOOL is_rsa,
// Manually set a signature (same reason as before) // Manually set a signature (same reason as before)
ASN1_BIT_STRING_set_bit(cert->signature, 8, 1); ASN1_BIT_STRING_set_bit(cert->signature, 8, 1);
ASN1_BIT_STRING_set(cert->signature, (unsigned char*)"\x00", 1); ASN1_BIT_STRING_set(cert->signature, (unsigned char*)"\x00", 1);
ASN1_BIT_STRING_set(cert->signature, (unsigned char*)"\x00", 1);
#endif
len = i2d_X509(cert, NULL); len = i2d_X509(cert, NULL);
if (len < 0) if (len < 0)
@@ -316,7 +319,7 @@ CK_RV do_store_pubk(X509 *cert, EVP_PKEY **key) {
CK_KEY_TYPE do_get_key_type(EVP_PKEY *key) { CK_KEY_TYPE do_get_key_type(EVP_PKEY *key) {
switch (key->type) { switch (EVP_PKEY_id(key)) {
case EVP_PKEY_RSA: case EVP_PKEY_RSA:
case EVP_PKEY_RSA2: case EVP_PKEY_RSA2:
return CKK_RSA; return CKK_RSA;
@@ -349,18 +352,20 @@ CK_ULONG do_get_rsa_modulus_length(EVP_PKEY *key) {
CK_RV do_get_modulus(EVP_PKEY *key, CK_BYTE_PTR data, CK_ULONG_PTR len) { CK_RV do_get_modulus(EVP_PKEY *key, CK_BYTE_PTR data, CK_ULONG_PTR len) {
RSA *rsa; RSA *rsa;
const BIGNUM *n;
rsa = EVP_PKEY_get1_RSA(key); rsa = EVP_PKEY_get1_RSA(key);
if (rsa == NULL) if (rsa == NULL)
return CKR_FUNCTION_FAILED; return CKR_FUNCTION_FAILED;
if ((CK_ULONG)BN_num_bytes(rsa->n) > *len) { RSA_get0_key(rsa, &n, NULL, NULL);
if ((CK_ULONG)BN_num_bytes(n) > *len) {
RSA_free(rsa); RSA_free(rsa);
rsa = NULL; rsa = NULL;
return CKR_BUFFER_TOO_SMALL; return CKR_BUFFER_TOO_SMALL;
} }
*len = (CK_ULONG)BN_bn2bin(rsa->n, data); *len = (CK_ULONG)BN_bn2bin(n, data);
RSA_free(rsa); RSA_free(rsa);
rsa = NULL; rsa = NULL;
@@ -372,18 +377,20 @@ CK_RV do_get_public_exponent(EVP_PKEY *key, CK_BYTE_PTR data, CK_ULONG_PTR len)
CK_ULONG e = 0; CK_ULONG e = 0;
RSA *rsa; RSA *rsa;
const BIGNUM *bn_e;
rsa = EVP_PKEY_get1_RSA(key); rsa = EVP_PKEY_get1_RSA(key);
if (rsa == NULL) if (rsa == NULL)
return CKR_FUNCTION_FAILED; return CKR_FUNCTION_FAILED;
if ((CK_ULONG)BN_num_bytes(rsa->e) > *len) { RSA_get0_key(rsa, NULL, &bn_e, NULL);
if ((CK_ULONG)BN_num_bytes(bn_e) > *len) {
RSA_free(rsa); RSA_free(rsa);
rsa = NULL; rsa = NULL;
return CKR_BUFFER_TOO_SMALL; return CKR_BUFFER_TOO_SMALL;
} }
*len = (CK_ULONG)BN_bn2bin(rsa->e, data); *len = (CK_ULONG)BN_bn2bin(bn_e, data);
RSA_free(rsa); RSA_free(rsa);
rsa = NULL; rsa = NULL;
@@ -406,7 +413,7 @@ CK_RV do_get_public_key(EVP_PKEY *key, CK_BYTE_PTR data, CK_ULONG_PTR len) {
const EC_POINT *ecp; const EC_POINT *ecp;
point_conversion_form_t pcf = POINT_CONVERSION_UNCOMPRESSED; point_conversion_form_t pcf = POINT_CONVERSION_UNCOMPRESSED;
switch(key->type) { switch(EVP_PKEY_id(key)) {
case EVP_PKEY_RSA: case EVP_PKEY_RSA:
case EVP_PKEY_RSA2: case EVP_PKEY_RSA2:
@@ -470,16 +477,20 @@ CK_RV do_get_public_key(EVP_PKEY *key, CK_BYTE_PTR data, CK_ULONG_PTR len) {
CK_RV do_encode_rsa_public_key(ykcs11_rsa_key_t **key, CK_BYTE_PTR modulus, CK_RV do_encode_rsa_public_key(ykcs11_rsa_key_t **key, CK_BYTE_PTR modulus,
CK_ULONG mlen, CK_BYTE_PTR exponent, CK_ULONG elen) { CK_ULONG mlen, CK_BYTE_PTR exponent, CK_ULONG elen) {
ykcs11_rsa_key_t *k; ykcs11_rsa_key_t *k;
BIGNUM *k_n = NULL, *k_e = NULL;
if (modulus == NULL || exponent == NULL) if (modulus == NULL || exponent == NULL)
return CKR_ARGUMENTS_BAD; return CKR_ARGUMENTS_BAD;
if ((k = RSA_new()) == NULL) if ((k = RSA_new()) == NULL)
return CKR_HOST_MEMORY; return CKR_HOST_MEMORY;
if ((k->n = BN_bin2bn(modulus, mlen, NULL)) == NULL) if ((k_n = BN_bin2bn(modulus, mlen, NULL)) == NULL)
return CKR_FUNCTION_FAILED; return CKR_FUNCTION_FAILED;
if ((k->e = BN_bin2bn(exponent, elen, NULL)) == NULL) if ((k_e = BN_bin2bn(exponent, elen, NULL)) == NULL)
return CKR_FUNCTION_FAILED;
if (RSA_set0_key(k, k_n, k_e, NULL) == 0)
return CKR_FUNCTION_FAILED; return CKR_FUNCTION_FAILED;
*key = k; *key = k;
+45 -7
View File
@@ -273,6 +273,32 @@ static void test_login() {
} }
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
static int bogus_sign(int dtype, const unsigned char *m, unsigned int m_length,
unsigned char *sigret, unsigned int *siglen, const RSA *rsa) {
sigret = malloc(1);
sigret = "";
*siglen = 1;
return 0;
}
static void bogus_sign_cert(X509 *cert) {
EVP_PKEY *pkey = EVP_PKEY_new();
RSA *rsa = RSA_new();
RSA_METHOD *meth = RSA_meth_dup(RSA_get_default_method());
BIGNUM *e = BN_new();
BN_set_word(e, 65537);
RSA_generate_key_ex(rsa, 1024, e, NULL);
RSA_meth_set_sign(meth, bogus_sign);
RSA_set_method(rsa, meth);
EVP_PKEY_set1_RSA(pkey, rsa);
X509_sign(cert, pkey, EVP_md5());
EVP_PKEY_free(pkey);
}
#endif
// Import a newly generated P256 pvt key and a certificate // Import a newly generated P256 pvt key and a certificate
// to every slot and use the key to sign some data // to every slot and use the key to sign some data
static void test_import_and_sign_all_10() { static void test_import_and_sign_all_10() {
@@ -358,11 +384,15 @@ static void test_import_and_sign_all_10() {
X509_set_notBefore(cert, tm); X509_set_notBefore(cert, tm);
X509_set_notAfter(cert, tm); X509_set_notAfter(cert, tm);
#if OPENSSL_VERSION_NUMBER < 0x10100000L
cert->sig_alg->algorithm = OBJ_nid2obj(8); cert->sig_alg->algorithm = OBJ_nid2obj(8);
cert->cert_info->signature->algorithm = OBJ_nid2obj(8); cert->cert_info->signature->algorithm = OBJ_nid2obj(8);
ASN1_BIT_STRING_set_bit(cert->signature, 8, 1); ASN1_BIT_STRING_set_bit(cert->signature, 8, 1);
ASN1_BIT_STRING_set(cert->signature, "\x00", 1); ASN1_BIT_STRING_set(cert->signature, "\x00", 1);
#else
bogus_sign_cert(cert);
#endif
p = value_c; p = value_c;
if ((cert_len = (CK_ULONG) i2d_X509(cert, &p)) == 0 || cert_len > sizeof(value_c)) if ((cert_len = (CK_ULONG) i2d_X509(cert, &p)) == 0 || cert_len > sizeof(value_c))
@@ -385,7 +415,7 @@ static void test_import_and_sign_all_10() {
for (i = 0; i < 24; i++) { for (i = 0; i < 24; i++) {
for (j = 0; j < 10; j++) { for (j = 0; j < 10; j++) {
if(RAND_pseudo_bytes(some_data, sizeof(some_data)) == -1) if(RAND_bytes(some_data, sizeof(some_data)) == -1)
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
asrt(funcs->C_Login(session, CKU_USER, "123456", 6), CKR_OK, "Login USER"); asrt(funcs->C_Login(session, CKU_USER, "123456", 6), CKR_OK, "Login USER");
@@ -480,6 +510,7 @@ static void test_import_and_sign_all_10_RSA() {
CK_BYTE_PTR s_ptr; CK_BYTE_PTR s_ptr;
CK_ULONG r_len; CK_ULONG r_len;
CK_ULONG s_len; CK_ULONG s_len;
const BIGNUM *bp, *bq, *biqmp, *bdmp1, *bdmq1;
unsigned char *px; unsigned char *px;
@@ -522,11 +553,13 @@ static void test_import_and_sign_all_10_RSA() {
asrt(RSA_generate_key_ex(rsak, 1024, e_bn, NULL), 1, "GENERATE RSAK"); asrt(RSA_generate_key_ex(rsak, 1024, e_bn, NULL), 1, "GENERATE RSAK");
asrt(BN_bn2bin(rsak->p, p), 64, "GET P"); RSA_get0_factors(rsak, &bp, &bq);
asrt(BN_bn2bin(rsak->q, q), 64, "GET Q"); RSA_get0_crt_params(rsak, &bdmp1, &bdmq1, &biqmp);
asrt(BN_bn2bin(rsak->dmp1, dp), 64, "GET DP"); asrt(BN_bn2bin(bp, p), 64, "GET P");
asrt(BN_bn2bin(rsak->dmq1, dp), 64, "GET DQ"); asrt(BN_bn2bin(bq, q), 64, "GET Q");
asrt(BN_bn2bin(rsak->iqmp, qinv), 64, "GET QINV"); asrt(BN_bn2bin(bdmp1, dp), 64, "GET DP");
asrt(BN_bn2bin(bdmq1, dp), 64, "GET DQ");
asrt(BN_bn2bin(biqmp, qinv), 64, "GET QINV");
@@ -549,11 +582,16 @@ static void test_import_and_sign_all_10_RSA() {
X509_set_notBefore(cert, tm); X509_set_notBefore(cert, tm);
X509_set_notAfter(cert, tm); X509_set_notAfter(cert, tm);
#if OPENSSL_VERSION_NUMBER < 0x10100000L
/* putting bogus data to signature to make some checks happy */
cert->sig_alg->algorithm = OBJ_nid2obj(8); cert->sig_alg->algorithm = OBJ_nid2obj(8);
cert->cert_info->signature->algorithm = OBJ_nid2obj(8); cert->cert_info->signature->algorithm = OBJ_nid2obj(8);
ASN1_BIT_STRING_set_bit(cert->signature, 8, 1); ASN1_BIT_STRING_set_bit(cert->signature, 8, 1);
ASN1_BIT_STRING_set(cert->signature, "\x00", 1); ASN1_BIT_STRING_set(cert->signature, "\x00", 1);
#else
bogus_sign_cert(cert);
#endif
px = value_c; px = value_c;
if ((cert_len = (CK_ULONG) i2d_X509(cert, &px)) == 0 || cert_len > sizeof(value_c)) if ((cert_len = (CK_ULONG) i2d_X509(cert, &px)) == 0 || cert_len > sizeof(value_c))
@@ -576,7 +614,7 @@ static void test_import_and_sign_all_10_RSA() {
for (i = 0; i < 24; i++) { for (i = 0; i < 24; i++) {
for (j = 0; j < 10; j++) { for (j = 0; j < 10; j++) {
if(RAND_pseudo_bytes(some_data, sizeof(some_data)) == -1) if(RAND_bytes(some_data, sizeof(some_data)) == -1)
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
asrt(funcs->C_Login(session, CKU_USER, "123456", 6), CKR_OK, "Login USER"); asrt(funcs->C_Login(session, CKU_USER, "123456", 6), CKR_OK, "Login USER");