From fa1ba589f3feab2c1d8c87109d18978238a9877f Mon Sep 17 00:00:00 2001 From: "Dr. Stephen Henson" Date: Sat, 6 Mar 2010 18:05:05 +0000 Subject: [PATCH] Add algorithm specific signature printing. An individual ASN1 method can now print out signatures instead of the standard hex dump. More complex signatures (e.g. PSS) can print out more meaningful information. Sample DSA version included that prints out the signature parameters r, s. [Note EVP_PKEY_ASN1_METHOD is an application opaque structure so adding new fields in the middle has no compatibility issues] --- CHANGES | 8 ++++++++ crypto/asn1/asn1.h | 4 ++-- crypto/asn1/asn1_locl.h | 3 +++ crypto/asn1/t_x509.c | 33 ++++++++++++++++++++++++++++----- crypto/cmac/cm_ameth.c | 2 +- crypto/dh/dh_ameth.c | 1 + crypto/dsa/dsa_ameth.c | 39 +++++++++++++++++++++++++++++++++++++++ crypto/ec/ec_ameth.c | 1 + crypto/hmac/hm_ameth.c | 2 +- crypto/ossl_typ.h | 1 + crypto/rsa/rsa_ameth.c | 2 +- crypto/x509/x509.h | 1 + 12 files changed, 87 insertions(+), 10 deletions(-) diff --git a/CHANGES b/CHANGES index a51168ef92..11ccdce558 100644 --- a/CHANGES +++ b/CHANGES @@ -4,6 +4,14 @@ Changes between 1.0.0 and 1.1.0 [xx XXX xxxx] + *) Add algorithm specific signature printing. An individual ASN1 method + can now print out signatures instead of the standard hex dump. + + More complex signatures (e.g. PSS) can print out more meaningful + information. Include DSA version that prints out the signature + parameters r, s. + [Steve Henson] + *) Add -trusted_first option which attempts to find certificates in the trusted store even if an untrusted chain is also supplied. [Steve Henson] diff --git a/crypto/asn1/asn1.h b/crypto/asn1/asn1.h index 4f9f7f605f..6c94696ae8 100644 --- a/crypto/asn1/asn1.h +++ b/crypto/asn1/asn1.h @@ -235,7 +235,7 @@ typedef struct asn1_object_st */ #define ASN1_STRING_FLAG_MSTRING 0x040 /* This is the base type that holds just about everything :-) */ -typedef struct asn1_string_st +struct asn1_string_st { int length; int type; @@ -245,7 +245,7 @@ typedef struct asn1_string_st * input data has a non-zero 'unused bits' value, it will be * handled correctly */ long flags; - } ASN1_STRING; + }; /* ASN1_ENCODING structure: this is used to save the received * encoding of an ASN1 type. This is useful to get round diff --git a/crypto/asn1/asn1_locl.h b/crypto/asn1/asn1_locl.h index 5aa65e28f5..6f3781045d 100644 --- a/crypto/asn1/asn1_locl.h +++ b/crypto/asn1/asn1_locl.h @@ -102,6 +102,9 @@ struct evp_pkey_asn1_method_st 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); + int (*sig_print)(BIO *out, + const X509_ALGOR *sigalg, const ASN1_STRING *sig, + int indent, ASN1_PCTX *pctx); void (*pkey_free)(EVP_PKEY *pkey); int (*pkey_ctrl)(EVP_PKEY *pkey, int op, long arg1, void *arg2); diff --git a/crypto/asn1/t_x509.c b/crypto/asn1/t_x509.c index 01cf9e427a..22041a8fc5 100644 --- a/crypto/asn1/t_x509.c +++ b/crypto/asn1/t_x509.c @@ -72,6 +72,7 @@ #include #include #include +#include "asn1_locl.h" #ifndef OPENSSL_NO_FP_API int X509_print_fp(FILE *fp, X509 *x) @@ -286,26 +287,48 @@ err: return(0); } -int X509_signature_print(BIO *bp, X509_ALGOR *sigalg, ASN1_STRING *sig) +int X509_signature_dump(BIO *bp, const ASN1_STRING *sig, int indent) { - unsigned char *s; + const unsigned char *s; int i, n; - if (BIO_puts(bp," Signature Algorithm: ") <= 0) return 0; - if (i2a_ASN1_OBJECT(bp, sigalg->algorithm) <= 0) return 0; n=sig->length; s=sig->data; for (i=0; ialgorithm) <= 0) return 0; + + sig_nid = OBJ_obj2nid(sigalg->algorithm); + if (sig_nid != NID_undef) + { + int pkey_nid, dig_nid; + const EVP_PKEY_ASN1_METHOD *ameth; + if (OBJ_find_sigid_algs(sig_nid, &dig_nid, &pkey_nid)) + { + ameth = EVP_PKEY_asn1_find(NULL, pkey_nid); + if (ameth && ameth->sig_print) + return ameth->sig_print(bp, sigalg, sig, 9, 0); + } + } + + return X509_signature_dump(bp, sig, 9); +} + int ASN1_STRING_print(BIO *bp, const ASN1_STRING *v) { int i,n; diff --git a/crypto/cmac/cm_ameth.c b/crypto/cmac/cm_ameth.c index 58a1a9d02e..08fcb85f93 100644 --- a/crypto/cmac/cm_ameth.c +++ b/crypto/cmac/cm_ameth.c @@ -93,7 +93,7 @@ const EVP_PKEY_ASN1_METHOD cmac_asn1_meth = cmac_size, 0, - 0,0,0,0,0,0, + 0,0,0,0,0,0,0, cmac_key_free, 0, diff --git a/crypto/dh/dh_ameth.c b/crypto/dh/dh_ameth.c index 377caf96c9..02ec2d47b4 100644 --- a/crypto/dh/dh_ameth.c +++ b/crypto/dh/dh_ameth.c @@ -493,6 +493,7 @@ const EVP_PKEY_ASN1_METHOD dh_asn1_meth = dh_copy_parameters, dh_cmp_parameters, dh_param_print, + 0, int_dh_free, 0 diff --git a/crypto/dsa/dsa_ameth.c b/crypto/dsa/dsa_ameth.c index 5482330c84..539b51f951 100644 --- a/crypto/dsa/dsa_ameth.c +++ b/crypto/dsa/dsa_ameth.c @@ -542,6 +542,44 @@ static int old_dsa_priv_encode(const EVP_PKEY *pkey, unsigned char **pder) return i2d_DSAPrivateKey(pkey->pkey.dsa, pder); } +static int dsa_sig_print(BIO *bp, const X509_ALGOR *sigalg, + const ASN1_STRING *sig, + int indent, ASN1_PCTX *pctx) + { + DSA_SIG *dsa_sig; + const unsigned char *p = sig->data; + dsa_sig = d2i_DSA_SIG(NULL, &p, sig->length); + if (dsa_sig) + { + int rv = 0; + size_t buf_len = 0; + unsigned char *m=NULL; + update_buflen(dsa_sig->r, &buf_len); + update_buflen(dsa_sig->s, &buf_len); + m = OPENSSL_malloc(buf_len+10); + if (m == NULL) + { + DSAerr(DSA_F_DO_DSA_PRINT,ERR_R_MALLOC_FAILURE); + goto err; + } + + if (BIO_write(bp, "\n", 1) != 1) + goto err; + + if (!ASN1_bn_print(bp,"r: ",dsa_sig->r,m,indent)) + goto err; + if (!ASN1_bn_print(bp,"s: ",dsa_sig->s,m,indent)) + goto err; + rv = 1; + err: + if (m) + OPENSSL_free(m); + DSA_SIG_free(dsa_sig); + return rv; + } + return X509_signature_dump(bp, sig, indent); + } + static int dsa_pkey_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2) { switch (op) @@ -647,6 +685,7 @@ const EVP_PKEY_ASN1_METHOD dsa_asn1_meths[] = dsa_copy_parameters, dsa_cmp_parameters, dsa_param_print, + dsa_sig_print, int_dsa_free, dsa_pkey_ctrl, diff --git a/crypto/ec/ec_ameth.c b/crypto/ec/ec_ameth.c index c00f7d746c..83909c1853 100644 --- a/crypto/ec/ec_ameth.c +++ b/crypto/ec/ec_ameth.c @@ -651,6 +651,7 @@ const EVP_PKEY_ASN1_METHOD eckey_asn1_meth = ec_copy_parameters, ec_cmp_parameters, eckey_param_print, + 0, int_ec_free, ec_pkey_ctrl, diff --git a/crypto/hmac/hm_ameth.c b/crypto/hmac/hm_ameth.c index 6d8a89149e..e03f24aeda 100644 --- a/crypto/hmac/hm_ameth.c +++ b/crypto/hmac/hm_ameth.c @@ -153,7 +153,7 @@ const EVP_PKEY_ASN1_METHOD hmac_asn1_meth = hmac_size, 0, - 0,0,0,0,0,0, + 0,0,0,0,0,0,0, hmac_key_free, hmac_pkey_ctrl, diff --git a/crypto/ossl_typ.h b/crypto/ossl_typ.h index 12bd7014de..23447e8284 100644 --- a/crypto/ossl_typ.h +++ b/crypto/ossl_typ.h @@ -91,6 +91,7 @@ typedef struct asn1_string_st ASN1_TIME; typedef struct asn1_string_st ASN1_GENERALIZEDTIME; typedef struct asn1_string_st ASN1_VISIBLESTRING; typedef struct asn1_string_st ASN1_UTF8STRING; +typedef struct asn1_string_st ASN1_STRING; typedef int ASN1_BOOLEAN; typedef int ASN1_NULL; #endif diff --git a/crypto/rsa/rsa_ameth.c b/crypto/rsa/rsa_ameth.c index 8c3209885e..a3d85b1f44 100644 --- a/crypto/rsa/rsa_ameth.c +++ b/crypto/rsa/rsa_ameth.c @@ -333,7 +333,7 @@ const EVP_PKEY_ASN1_METHOD rsa_asn1_meths[] = int_rsa_size, rsa_bits, - 0,0,0,0,0,0, + 0,0,0,0,0,0,0, int_rsa_free, rsa_pkey_ctrl, diff --git a/crypto/x509/x509.h b/crypto/x509/x509.h index eb1b7c6b2d..9fbb0c809d 100644 --- a/crypto/x509/x509.h +++ b/crypto/x509/x509.h @@ -656,6 +656,7 @@ int NETSCAPE_SPKI_set_pubkey(NETSCAPE_SPKI *x, EVP_PKEY *pkey); int NETSCAPE_SPKI_print(BIO *out, NETSCAPE_SPKI *spki); +int X509_signature_dump(BIO *bp,const ASN1_STRING *sig, int indent); int X509_signature_print(BIO *bp,X509_ALGOR *alg, ASN1_STRING *sig); int X509_sign(X509 *x, EVP_PKEY *pkey, const EVP_MD *md); -- 2.34.1