Pull EVP_PKEY print hooks out of the main method table.
This allows the static linker to drop it in consumers which don't need this stuff (i.e. all sane ones), once crypto/x509 falls off. This cuts down on a number of dependencies from the core crypto bits on crypto/asn1 and crypto/x509. BUG=499653 Change-Id: I76a10a04dcc444c1ded31683df9f87725a95a4e6 Reviewed-on: https://boringssl-review.googlesource.com/5660 Reviewed-by: Adam Langley <agl@google.com>
This commit is contained in:
committed by
Adam Langley
parent
17727c6843
commit
8c07ad3e3b
@@ -15,6 +15,7 @@ add_library(
|
||||
p_rsa.c
|
||||
p_rsa_asn1.c
|
||||
pbkdf.c
|
||||
print.c
|
||||
sign.c
|
||||
)
|
||||
|
||||
|
||||
@@ -59,7 +59,6 @@
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl/bio.h>
|
||||
#include <openssl/dsa.h>
|
||||
#include <openssl/ec.h>
|
||||
#include <openssl/err.h>
|
||||
@@ -358,41 +357,6 @@ int EVP_PKEY_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b) {
|
||||
return -2;
|
||||
}
|
||||
|
||||
static int print_unsupported(BIO *out, const EVP_PKEY *pkey, int indent,
|
||||
const char *kstr) {
|
||||
BIO_indent(out, indent, 128);
|
||||
BIO_printf(out, "%s algorithm \"%s\" unsupported\n", kstr,
|
||||
OBJ_nid2ln(pkey->type));
|
||||
return 1;
|
||||
}
|
||||
|
||||
int EVP_PKEY_print_public(BIO *out, const EVP_PKEY *pkey, int indent,
|
||||
ASN1_PCTX *pctx) {
|
||||
if (pkey->ameth && pkey->ameth->pub_print) {
|
||||
return pkey->ameth->pub_print(out, pkey, indent, pctx);
|
||||
}
|
||||
|
||||
return print_unsupported(out, pkey, indent, "Public Key");
|
||||
}
|
||||
|
||||
int EVP_PKEY_print_private(BIO *out, const EVP_PKEY *pkey, int indent,
|
||||
ASN1_PCTX *pctx) {
|
||||
if (pkey->ameth && pkey->ameth->priv_print) {
|
||||
return pkey->ameth->priv_print(out, pkey, indent, pctx);
|
||||
}
|
||||
|
||||
return print_unsupported(out, pkey, indent, "Private Key");
|
||||
}
|
||||
|
||||
int EVP_PKEY_print_params(BIO *out, const EVP_PKEY *pkey, int indent,
|
||||
ASN1_PCTX *pctx) {
|
||||
if (pkey->ameth && pkey->ameth->param_print) {
|
||||
return pkey->ameth->param_print(out, pkey, indent, pctx);
|
||||
}
|
||||
|
||||
return print_unsupported(out, pkey, indent, "Parameters");
|
||||
}
|
||||
|
||||
int EVP_PKEY_CTX_set_signature_md(EVP_PKEY_CTX *ctx, const EVP_MD *md) {
|
||||
return EVP_PKEY_CTX_ctrl(ctx, -1, EVP_PKEY_OP_TYPE_SIG, EVP_PKEY_CTRL_MD, 0,
|
||||
(void *)md);
|
||||
|
||||
@@ -59,6 +59,8 @@
|
||||
|
||||
#include <openssl/base.h>
|
||||
|
||||
#include <openssl/rsa.h>
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
@@ -83,7 +85,6 @@ struct evp_pkey_asn1_method_st {
|
||||
int (*pub_encode)(CBB *out, const EVP_PKEY *key);
|
||||
|
||||
int (*pub_cmp)(const EVP_PKEY *a, const EVP_PKEY *b);
|
||||
int (*pub_print)(BIO *out, const EVP_PKEY *pkey, int indent, ASN1_PCTX *pctx);
|
||||
|
||||
/* priv_decode decodes |params| and |key| as a PrivateKeyInfo and writes the
|
||||
* result into |out|. It returns one on success and zero on error. |params| is
|
||||
@@ -95,9 +96,6 @@ struct evp_pkey_asn1_method_st {
|
||||
* |out|. It returns one on success and zero on error. */
|
||||
int (*priv_encode)(CBB *out, const EVP_PKEY *key);
|
||||
|
||||
int (*priv_print)(BIO *out, const EVP_PKEY *pkey, int indent,
|
||||
ASN1_PCTX *pctx);
|
||||
|
||||
/* pkey_opaque returns 1 if the |pk| is opaque. Opaque keys are backed by
|
||||
* custom implementations which do not expose key material and parameters.*/
|
||||
int (*pkey_opaque)(const EVP_PKEY *pk);
|
||||
@@ -114,8 +112,6 @@ struct evp_pkey_asn1_method_st {
|
||||
int (*param_missing)(const EVP_PKEY *pk);
|
||||
int (*param_copy)(EVP_PKEY *to, const EVP_PKEY *from);
|
||||
int (*param_cmp)(const EVP_PKEY *a, const EVP_PKEY *b);
|
||||
int (*param_print)(BIO *out, const EVP_PKEY *pkey, int indent,
|
||||
ASN1_PCTX *pctx);
|
||||
|
||||
void (*pkey_free)(EVP_PKEY *pkey);
|
||||
|
||||
|
||||
@@ -55,14 +55,11 @@
|
||||
|
||||
#include <openssl/evp.h>
|
||||
|
||||
#include <openssl/asn1.h>
|
||||
#include <openssl/asn1t.h>
|
||||
#include <openssl/digest.h>
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/bytestring.h>
|
||||
#include <openssl/dsa.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.h>
|
||||
#include <openssl/obj.h>
|
||||
|
||||
#include "internal.h"
|
||||
@@ -244,91 +241,6 @@ static int dsa_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b) {
|
||||
|
||||
static void int_dsa_free(EVP_PKEY *pkey) { DSA_free(pkey->pkey.dsa); }
|
||||
|
||||
static void update_buflen(const BIGNUM *b, size_t *pbuflen) {
|
||||
size_t i;
|
||||
|
||||
if (!b) {
|
||||
return;
|
||||
}
|
||||
i = BN_num_bytes(b);
|
||||
if (*pbuflen < i) {
|
||||
*pbuflen = i;
|
||||
}
|
||||
}
|
||||
|
||||
static int do_dsa_print(BIO *bp, const DSA *x, int off, int ptype) {
|
||||
uint8_t *m = NULL;
|
||||
int ret = 0;
|
||||
size_t buf_len = 0;
|
||||
const char *ktype = NULL;
|
||||
|
||||
const BIGNUM *priv_key, *pub_key;
|
||||
|
||||
priv_key = NULL;
|
||||
if (ptype == 2) {
|
||||
priv_key = x->priv_key;
|
||||
}
|
||||
|
||||
pub_key = NULL;
|
||||
if (ptype > 0) {
|
||||
pub_key = x->pub_key;
|
||||
}
|
||||
|
||||
ktype = "DSA-Parameters";
|
||||
if (ptype == 2) {
|
||||
ktype = "Private-Key";
|
||||
} else if (ptype == 1) {
|
||||
ktype = "Public-Key";
|
||||
}
|
||||
|
||||
update_buflen(x->p, &buf_len);
|
||||
update_buflen(x->q, &buf_len);
|
||||
update_buflen(x->g, &buf_len);
|
||||
update_buflen(priv_key, &buf_len);
|
||||
update_buflen(pub_key, &buf_len);
|
||||
|
||||
m = OPENSSL_malloc(buf_len + 10);
|
||||
if (m == NULL) {
|
||||
OPENSSL_PUT_ERROR(EVP, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (priv_key) {
|
||||
if (!BIO_indent(bp, off, 128) ||
|
||||
BIO_printf(bp, "%s: (%d bit)\n", ktype, BN_num_bits(x->p)) <= 0) {
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
if (!ASN1_bn_print(bp, "priv:", priv_key, m, off) ||
|
||||
!ASN1_bn_print(bp, "pub: ", pub_key, m, off) ||
|
||||
!ASN1_bn_print(bp, "P: ", x->p, m, off) ||
|
||||
!ASN1_bn_print(bp, "Q: ", x->q, m, off) ||
|
||||
!ASN1_bn_print(bp, "G: ", x->g, m, off)) {
|
||||
goto err;
|
||||
}
|
||||
ret = 1;
|
||||
|
||||
err:
|
||||
OPENSSL_free(m);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int dsa_param_print(BIO *bp, const EVP_PKEY *pkey, int indent,
|
||||
ASN1_PCTX *ctx) {
|
||||
return do_dsa_print(bp, pkey->pkey.dsa, indent, 0);
|
||||
}
|
||||
|
||||
static int dsa_pub_print(BIO *bp, const EVP_PKEY *pkey, int indent,
|
||||
ASN1_PCTX *ctx) {
|
||||
return do_dsa_print(bp, pkey->pkey.dsa, indent, 1);
|
||||
}
|
||||
|
||||
static int dsa_priv_print(BIO *bp, const EVP_PKEY *pkey, int indent,
|
||||
ASN1_PCTX *ctx) {
|
||||
return do_dsa_print(bp, pkey->pkey.dsa, indent, 2);
|
||||
}
|
||||
|
||||
static int old_dsa_priv_decode(EVP_PKEY *pkey, const uint8_t **pder,
|
||||
int derlen) {
|
||||
DSA *dsa;
|
||||
@@ -348,11 +260,9 @@ const EVP_PKEY_ASN1_METHOD dsa_asn1_meth = {
|
||||
dsa_pub_decode,
|
||||
dsa_pub_encode,
|
||||
dsa_pub_cmp,
|
||||
dsa_pub_print,
|
||||
|
||||
dsa_priv_decode,
|
||||
dsa_priv_encode,
|
||||
dsa_priv_print,
|
||||
|
||||
NULL /* pkey_opaque */,
|
||||
NULL /* pkey_supports_digest */,
|
||||
@@ -363,7 +273,6 @@ const EVP_PKEY_ASN1_METHOD dsa_asn1_meth = {
|
||||
dsa_missing_parameters,
|
||||
dsa_copy_parameters,
|
||||
dsa_cmp_parameters,
|
||||
dsa_param_print,
|
||||
|
||||
int_dsa_free,
|
||||
old_dsa_priv_decode,
|
||||
|
||||
@@ -55,14 +55,12 @@
|
||||
|
||||
#include <openssl/evp.h>
|
||||
|
||||
#include <openssl/asn1t.h>
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/bytestring.h>
|
||||
#include <openssl/ec.h>
|
||||
#include <openssl/ec_key.h>
|
||||
#include <openssl/ecdsa.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.h>
|
||||
#include <openssl/obj.h>
|
||||
|
||||
#include "internal.h"
|
||||
@@ -236,125 +234,6 @@ static int ec_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b) {
|
||||
|
||||
static void int_ec_free(EVP_PKEY *pkey) { EC_KEY_free(pkey->pkey.ec); }
|
||||
|
||||
static int do_EC_KEY_print(BIO *bp, const EC_KEY *x, int off, int ktype) {
|
||||
uint8_t *buffer = NULL;
|
||||
const char *ecstr;
|
||||
size_t buf_len = 0, i;
|
||||
int ret = 0, reason = ERR_R_BIO_LIB;
|
||||
BN_CTX *ctx = NULL;
|
||||
const EC_GROUP *group;
|
||||
const EC_POINT *public_key;
|
||||
const BIGNUM *priv_key;
|
||||
uint8_t *pub_key_bytes = NULL;
|
||||
size_t pub_key_bytes_len = 0;
|
||||
|
||||
if (x == NULL || (group = EC_KEY_get0_group(x)) == NULL) {
|
||||
reason = ERR_R_PASSED_NULL_PARAMETER;
|
||||
goto err;
|
||||
}
|
||||
|
||||
ctx = BN_CTX_new();
|
||||
if (ctx == NULL) {
|
||||
reason = ERR_R_MALLOC_FAILURE;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (ktype > 0) {
|
||||
public_key = EC_KEY_get0_public_key(x);
|
||||
if (public_key != NULL) {
|
||||
pub_key_bytes_len = EC_POINT_point2oct(
|
||||
group, public_key, EC_KEY_get_conv_form(x), NULL, 0, ctx);
|
||||
if (pub_key_bytes_len == 0) {
|
||||
reason = ERR_R_MALLOC_FAILURE;
|
||||
goto err;
|
||||
}
|
||||
pub_key_bytes = OPENSSL_malloc(pub_key_bytes_len);
|
||||
if (pub_key_bytes == NULL) {
|
||||
reason = ERR_R_MALLOC_FAILURE;
|
||||
goto err;
|
||||
}
|
||||
pub_key_bytes_len =
|
||||
EC_POINT_point2oct(group, public_key, EC_KEY_get_conv_form(x),
|
||||
pub_key_bytes, pub_key_bytes_len, ctx);
|
||||
if (pub_key_bytes_len == 0) {
|
||||
reason = ERR_R_MALLOC_FAILURE;
|
||||
goto err;
|
||||
}
|
||||
buf_len = pub_key_bytes_len;
|
||||
}
|
||||
}
|
||||
|
||||
if (ktype == 2) {
|
||||
priv_key = EC_KEY_get0_private_key(x);
|
||||
if (priv_key && (i = (size_t)BN_num_bytes(priv_key)) > buf_len) {
|
||||
buf_len = i;
|
||||
}
|
||||
} else {
|
||||
priv_key = NULL;
|
||||
}
|
||||
|
||||
if (ktype > 0) {
|
||||
buf_len += 10;
|
||||
if ((buffer = OPENSSL_malloc(buf_len)) == NULL) {
|
||||
reason = ERR_R_MALLOC_FAILURE;
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
if (ktype == 2) {
|
||||
ecstr = "Private-Key";
|
||||
} else if (ktype == 1) {
|
||||
ecstr = "Public-Key";
|
||||
} else {
|
||||
ecstr = "ECDSA-Parameters";
|
||||
}
|
||||
|
||||
if (!BIO_indent(bp, off, 128)) {
|
||||
goto err;
|
||||
}
|
||||
const BIGNUM *order = EC_GROUP_get0_order(group);
|
||||
if (BIO_printf(bp, "%s: (%d bit)\n", ecstr, BN_num_bits(order)) <= 0) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
if ((priv_key != NULL) &&
|
||||
!ASN1_bn_print(bp, "priv:", priv_key, buffer, off)) {
|
||||
goto err;
|
||||
}
|
||||
if (pub_key_bytes != NULL) {
|
||||
BIO_hexdump(bp, pub_key_bytes, pub_key_bytes_len, off);
|
||||
}
|
||||
/* TODO(fork): implement */
|
||||
/*
|
||||
if (!ECPKParameters_print(bp, group, off))
|
||||
goto err; */
|
||||
ret = 1;
|
||||
|
||||
err:
|
||||
if (!ret) {
|
||||
OPENSSL_PUT_ERROR(EVP, reason);
|
||||
}
|
||||
OPENSSL_free(pub_key_bytes);
|
||||
BN_CTX_free(ctx);
|
||||
OPENSSL_free(buffer);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int eckey_param_print(BIO *bp, const EVP_PKEY *pkey, int indent,
|
||||
ASN1_PCTX *ctx) {
|
||||
return do_EC_KEY_print(bp, pkey->pkey.ec, indent, 0);
|
||||
}
|
||||
|
||||
static int eckey_pub_print(BIO *bp, const EVP_PKEY *pkey, int indent,
|
||||
ASN1_PCTX *ctx) {
|
||||
return do_EC_KEY_print(bp, pkey->pkey.ec, indent, 1);
|
||||
}
|
||||
|
||||
|
||||
static int eckey_priv_print(BIO *bp, const EVP_PKEY *pkey, int indent,
|
||||
ASN1_PCTX *ctx) {
|
||||
return do_EC_KEY_print(bp, pkey->pkey.ec, indent, 2);
|
||||
}
|
||||
|
||||
static int eckey_opaque(const EVP_PKEY *pkey) {
|
||||
return EC_KEY_is_opaque(pkey->pkey.ec);
|
||||
}
|
||||
@@ -377,11 +256,9 @@ const EVP_PKEY_ASN1_METHOD ec_asn1_meth = {
|
||||
eckey_pub_decode,
|
||||
eckey_pub_encode,
|
||||
eckey_pub_cmp,
|
||||
eckey_pub_print,
|
||||
|
||||
eckey_priv_decode,
|
||||
eckey_priv_encode,
|
||||
eckey_priv_print,
|
||||
|
||||
eckey_opaque,
|
||||
0 /* pkey_supports_digest */,
|
||||
@@ -392,7 +269,6 @@ const EVP_PKEY_ASN1_METHOD ec_asn1_meth = {
|
||||
ec_missing_parameters,
|
||||
ec_copy_parameters,
|
||||
ec_cmp_parameters,
|
||||
eckey_param_print,
|
||||
|
||||
int_ec_free,
|
||||
old_ec_priv_decode,
|
||||
|
||||
+2
-131
@@ -55,7 +55,7 @@
|
||||
|
||||
#include <openssl/evp.h>
|
||||
|
||||
#include <openssl/asn1.h>
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/bytestring.h>
|
||||
#include <openssl/digest.h>
|
||||
#include <openssl/err.h>
|
||||
@@ -175,133 +175,6 @@ static int rsa_bits(const EVP_PKEY *pkey) {
|
||||
|
||||
static void int_rsa_free(EVP_PKEY *pkey) { RSA_free(pkey->pkey.rsa); }
|
||||
|
||||
static void update_buflen(const BIGNUM *b, size_t *pbuflen) {
|
||||
size_t i;
|
||||
|
||||
if (!b) {
|
||||
return;
|
||||
}
|
||||
|
||||
i = BN_num_bytes(b);
|
||||
if (*pbuflen < i) {
|
||||
*pbuflen = i;
|
||||
}
|
||||
}
|
||||
|
||||
static int do_rsa_print(BIO *out, const RSA *rsa, int off,
|
||||
int include_private) {
|
||||
char *str;
|
||||
const char *s;
|
||||
uint8_t *m = NULL;
|
||||
int ret = 0, mod_len = 0;
|
||||
size_t buf_len = 0;
|
||||
|
||||
update_buflen(rsa->n, &buf_len);
|
||||
update_buflen(rsa->e, &buf_len);
|
||||
|
||||
if (include_private) {
|
||||
update_buflen(rsa->d, &buf_len);
|
||||
update_buflen(rsa->p, &buf_len);
|
||||
update_buflen(rsa->q, &buf_len);
|
||||
update_buflen(rsa->dmp1, &buf_len);
|
||||
update_buflen(rsa->dmq1, &buf_len);
|
||||
update_buflen(rsa->iqmp, &buf_len);
|
||||
|
||||
if (rsa->additional_primes != NULL) {
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < sk_RSA_additional_prime_num(rsa->additional_primes);
|
||||
i++) {
|
||||
const RSA_additional_prime *ap =
|
||||
sk_RSA_additional_prime_value(rsa->additional_primes, i);
|
||||
update_buflen(ap->prime, &buf_len);
|
||||
update_buflen(ap->exp, &buf_len);
|
||||
update_buflen(ap->coeff, &buf_len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m = OPENSSL_malloc(buf_len + 10);
|
||||
if (m == NULL) {
|
||||
OPENSSL_PUT_ERROR(EVP, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (rsa->n != NULL) {
|
||||
mod_len = BN_num_bits(rsa->n);
|
||||
}
|
||||
|
||||
if (!BIO_indent(out, off, 128)) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (include_private && rsa->d) {
|
||||
if (BIO_printf(out, "Private-Key: (%d bit)\n", mod_len) <= 0) {
|
||||
goto err;
|
||||
}
|
||||
str = "modulus:";
|
||||
s = "publicExponent:";
|
||||
} else {
|
||||
if (BIO_printf(out, "Public-Key: (%d bit)\n", mod_len) <= 0) {
|
||||
goto err;
|
||||
}
|
||||
str = "Modulus:";
|
||||
s = "Exponent:";
|
||||
}
|
||||
if (!ASN1_bn_print(out, str, rsa->n, m, off) ||
|
||||
!ASN1_bn_print(out, s, rsa->e, m, off)) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (include_private) {
|
||||
if (!ASN1_bn_print(out, "privateExponent:", rsa->d, m, off) ||
|
||||
!ASN1_bn_print(out, "prime1:", rsa->p, m, off) ||
|
||||
!ASN1_bn_print(out, "prime2:", rsa->q, m, off) ||
|
||||
!ASN1_bn_print(out, "exponent1:", rsa->dmp1, m, off) ||
|
||||
!ASN1_bn_print(out, "exponent2:", rsa->dmq1, m, off) ||
|
||||
!ASN1_bn_print(out, "coefficient:", rsa->iqmp, m, off)) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (rsa->additional_primes != NULL &&
|
||||
sk_RSA_additional_prime_num(rsa->additional_primes) > 0) {
|
||||
size_t i;
|
||||
|
||||
if (BIO_printf(out, "otherPrimeInfos:\n") <= 0) {
|
||||
goto err;
|
||||
}
|
||||
for (i = 0; i < sk_RSA_additional_prime_num(rsa->additional_primes);
|
||||
i++) {
|
||||
const RSA_additional_prime *ap =
|
||||
sk_RSA_additional_prime_value(rsa->additional_primes, i);
|
||||
|
||||
if (BIO_printf(out, "otherPrimeInfo (prime %u):\n",
|
||||
(unsigned)(i + 3)) <= 0 ||
|
||||
!ASN1_bn_print(out, "prime:", ap->prime, m, off) ||
|
||||
!ASN1_bn_print(out, "exponent:", ap->exp, m, off) ||
|
||||
!ASN1_bn_print(out, "coeff:", ap->coeff, m, off)) {
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ret = 1;
|
||||
|
||||
err:
|
||||
OPENSSL_free(m);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int rsa_pub_print(BIO *bp, const EVP_PKEY *pkey, int indent,
|
||||
ASN1_PCTX *ctx) {
|
||||
return do_rsa_print(bp, pkey->pkey.rsa, indent, 0);
|
||||
}
|
||||
|
||||
static int rsa_priv_print(BIO *bp, const EVP_PKEY *pkey, int indent,
|
||||
ASN1_PCTX *ctx) {
|
||||
return do_rsa_print(bp, pkey->pkey.rsa, indent, 1);
|
||||
}
|
||||
|
||||
static int old_rsa_priv_decode(EVP_PKEY *pkey, const uint8_t **pder,
|
||||
int derlen) {
|
||||
RSA *rsa = d2i_RSAPrivateKey(NULL, pder, derlen);
|
||||
@@ -320,11 +193,9 @@ const EVP_PKEY_ASN1_METHOD rsa_asn1_meth = {
|
||||
rsa_pub_decode,
|
||||
rsa_pub_encode,
|
||||
rsa_pub_cmp,
|
||||
rsa_pub_print,
|
||||
|
||||
rsa_priv_decode,
|
||||
rsa_priv_encode,
|
||||
rsa_priv_print,
|
||||
|
||||
rsa_opaque,
|
||||
rsa_supports_digest,
|
||||
@@ -332,7 +203,7 @@ const EVP_PKEY_ASN1_METHOD rsa_asn1_meth = {
|
||||
int_rsa_size,
|
||||
rsa_bits,
|
||||
|
||||
0,0,0,0,
|
||||
0,0,0,
|
||||
|
||||
int_rsa_free,
|
||||
|
||||
|
||||
@@ -0,0 +1,474 @@
|
||||
/* ====================================================================
|
||||
* Copyright (c) 2006 The OpenSSL Project. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. All advertising materials mentioning features or use of this
|
||||
* software must display the following acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
|
||||
*
|
||||
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
|
||||
* endorse or promote products derived from this software without
|
||||
* prior written permission. For written permission, please contact
|
||||
* licensing@OpenSSL.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "OpenSSL"
|
||||
* nor may "OpenSSL" appear in their names without prior written
|
||||
* permission of the OpenSSL Project.
|
||||
*
|
||||
* 6. Redistributions of any form whatsoever must retain the following
|
||||
* acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
|
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ====================================================================
|
||||
*
|
||||
* This product includes cryptographic software written by Eric Young
|
||||
* (eay@cryptsoft.com). This product includes software written by Tim
|
||||
* Hudson (tjh@cryptsoft.com). */
|
||||
|
||||
#include <openssl/evp.h>
|
||||
|
||||
#include <openssl/asn1.h>
|
||||
#include <openssl/bio.h>
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/dsa.h>
|
||||
#include <openssl/ec.h>
|
||||
#include <openssl/ec_key.h>
|
||||
#include <openssl/mem.h>
|
||||
#include <openssl/rsa.h>
|
||||
|
||||
#include "../rsa/internal.h"
|
||||
|
||||
|
||||
static void update_buflen(const BIGNUM *b, size_t *pbuflen) {
|
||||
size_t i;
|
||||
|
||||
if (!b) {
|
||||
return;
|
||||
}
|
||||
|
||||
i = BN_num_bytes(b);
|
||||
if (*pbuflen < i) {
|
||||
*pbuflen = i;
|
||||
}
|
||||
}
|
||||
|
||||
/* RSA keys. */
|
||||
|
||||
static int do_rsa_print(BIO *out, const RSA *rsa, int off,
|
||||
int include_private) {
|
||||
char *str;
|
||||
const char *s;
|
||||
uint8_t *m = NULL;
|
||||
int ret = 0, mod_len = 0;
|
||||
size_t buf_len = 0;
|
||||
|
||||
update_buflen(rsa->n, &buf_len);
|
||||
update_buflen(rsa->e, &buf_len);
|
||||
|
||||
if (include_private) {
|
||||
update_buflen(rsa->d, &buf_len);
|
||||
update_buflen(rsa->p, &buf_len);
|
||||
update_buflen(rsa->q, &buf_len);
|
||||
update_buflen(rsa->dmp1, &buf_len);
|
||||
update_buflen(rsa->dmq1, &buf_len);
|
||||
update_buflen(rsa->iqmp, &buf_len);
|
||||
|
||||
if (rsa->additional_primes != NULL) {
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < sk_RSA_additional_prime_num(rsa->additional_primes);
|
||||
i++) {
|
||||
const RSA_additional_prime *ap =
|
||||
sk_RSA_additional_prime_value(rsa->additional_primes, i);
|
||||
update_buflen(ap->prime, &buf_len);
|
||||
update_buflen(ap->exp, &buf_len);
|
||||
update_buflen(ap->coeff, &buf_len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m = (uint8_t *)OPENSSL_malloc(buf_len + 10);
|
||||
if (m == NULL) {
|
||||
OPENSSL_PUT_ERROR(EVP, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (rsa->n != NULL) {
|
||||
mod_len = BN_num_bits(rsa->n);
|
||||
}
|
||||
|
||||
if (!BIO_indent(out, off, 128)) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (include_private && rsa->d) {
|
||||
if (BIO_printf(out, "Private-Key: (%d bit)\n", mod_len) <= 0) {
|
||||
goto err;
|
||||
}
|
||||
str = "modulus:";
|
||||
s = "publicExponent:";
|
||||
} else {
|
||||
if (BIO_printf(out, "Public-Key: (%d bit)\n", mod_len) <= 0) {
|
||||
goto err;
|
||||
}
|
||||
str = "Modulus:";
|
||||
s = "Exponent:";
|
||||
}
|
||||
if (!ASN1_bn_print(out, str, rsa->n, m, off) ||
|
||||
!ASN1_bn_print(out, s, rsa->e, m, off)) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (include_private) {
|
||||
if (!ASN1_bn_print(out, "privateExponent:", rsa->d, m, off) ||
|
||||
!ASN1_bn_print(out, "prime1:", rsa->p, m, off) ||
|
||||
!ASN1_bn_print(out, "prime2:", rsa->q, m, off) ||
|
||||
!ASN1_bn_print(out, "exponent1:", rsa->dmp1, m, off) ||
|
||||
!ASN1_bn_print(out, "exponent2:", rsa->dmq1, m, off) ||
|
||||
!ASN1_bn_print(out, "coefficient:", rsa->iqmp, m, off)) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (rsa->additional_primes != NULL &&
|
||||
sk_RSA_additional_prime_num(rsa->additional_primes) > 0) {
|
||||
size_t i;
|
||||
|
||||
if (BIO_printf(out, "otherPrimeInfos:\n") <= 0) {
|
||||
goto err;
|
||||
}
|
||||
for (i = 0; i < sk_RSA_additional_prime_num(rsa->additional_primes);
|
||||
i++) {
|
||||
const RSA_additional_prime *ap =
|
||||
sk_RSA_additional_prime_value(rsa->additional_primes, i);
|
||||
|
||||
if (BIO_printf(out, "otherPrimeInfo (prime %u):\n",
|
||||
(unsigned)(i + 3)) <= 0 ||
|
||||
!ASN1_bn_print(out, "prime:", ap->prime, m, off) ||
|
||||
!ASN1_bn_print(out, "exponent:", ap->exp, m, off) ||
|
||||
!ASN1_bn_print(out, "coeff:", ap->coeff, m, off)) {
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ret = 1;
|
||||
|
||||
err:
|
||||
OPENSSL_free(m);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int rsa_pub_print(BIO *bp, const EVP_PKEY *pkey, int indent,
|
||||
ASN1_PCTX *ctx) {
|
||||
return do_rsa_print(bp, pkey->pkey.rsa, indent, 0);
|
||||
}
|
||||
|
||||
static int rsa_priv_print(BIO *bp, const EVP_PKEY *pkey, int indent,
|
||||
ASN1_PCTX *ctx) {
|
||||
return do_rsa_print(bp, pkey->pkey.rsa, indent, 1);
|
||||
}
|
||||
|
||||
|
||||
/* DSA keys. */
|
||||
|
||||
static int do_dsa_print(BIO *bp, const DSA *x, int off, int ptype) {
|
||||
uint8_t *m = NULL;
|
||||
int ret = 0;
|
||||
size_t buf_len = 0;
|
||||
const char *ktype = NULL;
|
||||
|
||||
const BIGNUM *priv_key, *pub_key;
|
||||
|
||||
priv_key = NULL;
|
||||
if (ptype == 2) {
|
||||
priv_key = x->priv_key;
|
||||
}
|
||||
|
||||
pub_key = NULL;
|
||||
if (ptype > 0) {
|
||||
pub_key = x->pub_key;
|
||||
}
|
||||
|
||||
ktype = "DSA-Parameters";
|
||||
if (ptype == 2) {
|
||||
ktype = "Private-Key";
|
||||
} else if (ptype == 1) {
|
||||
ktype = "Public-Key";
|
||||
}
|
||||
|
||||
update_buflen(x->p, &buf_len);
|
||||
update_buflen(x->q, &buf_len);
|
||||
update_buflen(x->g, &buf_len);
|
||||
update_buflen(priv_key, &buf_len);
|
||||
update_buflen(pub_key, &buf_len);
|
||||
|
||||
m = (uint8_t *)OPENSSL_malloc(buf_len + 10);
|
||||
if (m == NULL) {
|
||||
OPENSSL_PUT_ERROR(EVP, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (priv_key) {
|
||||
if (!BIO_indent(bp, off, 128) ||
|
||||
BIO_printf(bp, "%s: (%d bit)\n", ktype, BN_num_bits(x->p)) <= 0) {
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
if (!ASN1_bn_print(bp, "priv:", priv_key, m, off) ||
|
||||
!ASN1_bn_print(bp, "pub: ", pub_key, m, off) ||
|
||||
!ASN1_bn_print(bp, "P: ", x->p, m, off) ||
|
||||
!ASN1_bn_print(bp, "Q: ", x->q, m, off) ||
|
||||
!ASN1_bn_print(bp, "G: ", x->g, m, off)) {
|
||||
goto err;
|
||||
}
|
||||
ret = 1;
|
||||
|
||||
err:
|
||||
OPENSSL_free(m);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int dsa_param_print(BIO *bp, const EVP_PKEY *pkey, int indent,
|
||||
ASN1_PCTX *ctx) {
|
||||
return do_dsa_print(bp, pkey->pkey.dsa, indent, 0);
|
||||
}
|
||||
|
||||
static int dsa_pub_print(BIO *bp, const EVP_PKEY *pkey, int indent,
|
||||
ASN1_PCTX *ctx) {
|
||||
return do_dsa_print(bp, pkey->pkey.dsa, indent, 1);
|
||||
}
|
||||
|
||||
static int dsa_priv_print(BIO *bp, const EVP_PKEY *pkey, int indent,
|
||||
ASN1_PCTX *ctx) {
|
||||
return do_dsa_print(bp, pkey->pkey.dsa, indent, 2);
|
||||
}
|
||||
|
||||
|
||||
/* EC keys. */
|
||||
|
||||
static int do_EC_KEY_print(BIO *bp, const EC_KEY *x, int off, int ktype) {
|
||||
uint8_t *buffer = NULL;
|
||||
const char *ecstr;
|
||||
size_t buf_len = 0, i;
|
||||
int ret = 0, reason = ERR_R_BIO_LIB;
|
||||
BIGNUM *order = NULL;
|
||||
BN_CTX *ctx = NULL;
|
||||
const EC_GROUP *group;
|
||||
const EC_POINT *public_key;
|
||||
const BIGNUM *priv_key;
|
||||
uint8_t *pub_key_bytes = NULL;
|
||||
size_t pub_key_bytes_len = 0;
|
||||
|
||||
if (x == NULL || (group = EC_KEY_get0_group(x)) == NULL) {
|
||||
reason = ERR_R_PASSED_NULL_PARAMETER;
|
||||
goto err;
|
||||
}
|
||||
|
||||
ctx = BN_CTX_new();
|
||||
if (ctx == NULL) {
|
||||
reason = ERR_R_MALLOC_FAILURE;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (ktype > 0) {
|
||||
public_key = EC_KEY_get0_public_key(x);
|
||||
if (public_key != NULL) {
|
||||
pub_key_bytes_len = EC_POINT_point2oct(
|
||||
group, public_key, EC_KEY_get_conv_form(x), NULL, 0, ctx);
|
||||
if (pub_key_bytes_len == 0) {
|
||||
reason = ERR_R_MALLOC_FAILURE;
|
||||
goto err;
|
||||
}
|
||||
pub_key_bytes = OPENSSL_malloc(pub_key_bytes_len);
|
||||
if (pub_key_bytes == NULL) {
|
||||
reason = ERR_R_MALLOC_FAILURE;
|
||||
goto err;
|
||||
}
|
||||
pub_key_bytes_len =
|
||||
EC_POINT_point2oct(group, public_key, EC_KEY_get_conv_form(x),
|
||||
pub_key_bytes, pub_key_bytes_len, ctx);
|
||||
if (pub_key_bytes_len == 0) {
|
||||
reason = ERR_R_MALLOC_FAILURE;
|
||||
goto err;
|
||||
}
|
||||
buf_len = pub_key_bytes_len;
|
||||
}
|
||||
}
|
||||
|
||||
if (ktype == 2) {
|
||||
priv_key = EC_KEY_get0_private_key(x);
|
||||
if (priv_key && (i = (size_t)BN_num_bytes(priv_key)) > buf_len) {
|
||||
buf_len = i;
|
||||
}
|
||||
} else {
|
||||
priv_key = NULL;
|
||||
}
|
||||
|
||||
if (ktype > 0) {
|
||||
buf_len += 10;
|
||||
if ((buffer = OPENSSL_malloc(buf_len)) == NULL) {
|
||||
reason = ERR_R_MALLOC_FAILURE;
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
if (ktype == 2) {
|
||||
ecstr = "Private-Key";
|
||||
} else if (ktype == 1) {
|
||||
ecstr = "Public-Key";
|
||||
} else {
|
||||
ecstr = "ECDSA-Parameters";
|
||||
}
|
||||
|
||||
if (!BIO_indent(bp, off, 128)) {
|
||||
goto err;
|
||||
}
|
||||
order = BN_new();
|
||||
if (order == NULL || !EC_GROUP_get_order(group, order, NULL) ||
|
||||
BIO_printf(bp, "%s: (%d bit)\n", ecstr, BN_num_bits(order)) <= 0) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
if ((priv_key != NULL) &&
|
||||
!ASN1_bn_print(bp, "priv:", priv_key, buffer, off)) {
|
||||
goto err;
|
||||
}
|
||||
if (pub_key_bytes != NULL) {
|
||||
BIO_hexdump(bp, pub_key_bytes, pub_key_bytes_len, off);
|
||||
}
|
||||
/* TODO(fork): implement */
|
||||
/*
|
||||
if (!ECPKParameters_print(bp, group, off))
|
||||
goto err; */
|
||||
ret = 1;
|
||||
|
||||
err:
|
||||
if (!ret) {
|
||||
OPENSSL_PUT_ERROR(EVP, reason);
|
||||
}
|
||||
OPENSSL_free(pub_key_bytes);
|
||||
BN_free(order);
|
||||
BN_CTX_free(ctx);
|
||||
OPENSSL_free(buffer);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int eckey_param_print(BIO *bp, const EVP_PKEY *pkey, int indent,
|
||||
ASN1_PCTX *ctx) {
|
||||
return do_EC_KEY_print(bp, pkey->pkey.ec, indent, 0);
|
||||
}
|
||||
|
||||
static int eckey_pub_print(BIO *bp, const EVP_PKEY *pkey, int indent,
|
||||
ASN1_PCTX *ctx) {
|
||||
return do_EC_KEY_print(bp, pkey->pkey.ec, indent, 1);
|
||||
}
|
||||
|
||||
|
||||
static int eckey_priv_print(BIO *bp, const EVP_PKEY *pkey, int indent,
|
||||
ASN1_PCTX *ctx) {
|
||||
return do_EC_KEY_print(bp, pkey->pkey.ec, indent, 2);
|
||||
}
|
||||
|
||||
|
||||
typedef struct {
|
||||
int type;
|
||||
int (*pub_print)(BIO *out, const EVP_PKEY *pkey, int indent, ASN1_PCTX *pctx);
|
||||
int (*priv_print)(BIO *out, const EVP_PKEY *pkey, int indent,
|
||||
ASN1_PCTX *pctx);
|
||||
int (*param_print)(BIO *out, const EVP_PKEY *pkey, int indent,
|
||||
ASN1_PCTX *pctx);
|
||||
} EVP_PKEY_PRINT_METHOD;
|
||||
|
||||
static EVP_PKEY_PRINT_METHOD kPrintMethods[] = {
|
||||
{
|
||||
EVP_PKEY_RSA,
|
||||
rsa_pub_print,
|
||||
rsa_priv_print,
|
||||
NULL /* param_print */,
|
||||
},
|
||||
{
|
||||
EVP_PKEY_DSA,
|
||||
dsa_pub_print,
|
||||
dsa_priv_print,
|
||||
dsa_param_print,
|
||||
},
|
||||
{
|
||||
EVP_PKEY_EC,
|
||||
eckey_pub_print,
|
||||
eckey_priv_print,
|
||||
eckey_param_print,
|
||||
},
|
||||
};
|
||||
|
||||
static size_t kPrintMethodsLen =
|
||||
sizeof(kPrintMethods) / sizeof(kPrintMethods[0]);
|
||||
|
||||
static EVP_PKEY_PRINT_METHOD *find_method(int type) {
|
||||
size_t i;
|
||||
for (i = 0; i < kPrintMethodsLen; i++) {
|
||||
if (kPrintMethods[i].type == type) {
|
||||
return &kPrintMethods[i];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int print_unsupported(BIO *out, const EVP_PKEY *pkey, int indent,
|
||||
const char *kstr) {
|
||||
BIO_indent(out, indent, 128);
|
||||
BIO_printf(out, "%s algorithm \"%s\" unsupported\n", kstr,
|
||||
OBJ_nid2ln(pkey->type));
|
||||
return 1;
|
||||
}
|
||||
|
||||
int EVP_PKEY_print_public(BIO *out, const EVP_PKEY *pkey, int indent,
|
||||
ASN1_PCTX *pctx) {
|
||||
EVP_PKEY_PRINT_METHOD *method = find_method(pkey->type);
|
||||
if (method != NULL && method->pub_print != NULL) {
|
||||
return method->pub_print(out, pkey, indent, pctx);
|
||||
}
|
||||
return print_unsupported(out, pkey, indent, "Public Key");
|
||||
}
|
||||
|
||||
int EVP_PKEY_print_private(BIO *out, const EVP_PKEY *pkey, int indent,
|
||||
ASN1_PCTX *pctx) {
|
||||
EVP_PKEY_PRINT_METHOD *method = find_method(pkey->type);
|
||||
if (method != NULL && method->priv_print != NULL) {
|
||||
return method->priv_print(out, pkey, indent, pctx);
|
||||
}
|
||||
return print_unsupported(out, pkey, indent, "Private Key");
|
||||
}
|
||||
|
||||
int EVP_PKEY_print_params(BIO *out, const EVP_PKEY *pkey, int indent,
|
||||
ASN1_PCTX *pctx) {
|
||||
EVP_PKEY_PRINT_METHOD *method = find_method(pkey->type);
|
||||
if (method != NULL && method->param_print != NULL) {
|
||||
return method->param_print(out, pkey, indent, pctx);
|
||||
}
|
||||
return print_unsupported(out, pkey, indent, "Parameters");
|
||||
}
|
||||
Reference in New Issue
Block a user