summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsteve <steve>2012-03-06 14:28:19 +0000
committersteve <steve>2012-03-06 14:28:19 +0000
commita8a21a6972394c2f76894dce5e0b882998b3f410 (patch)
tree907951d6eaf802034249f1433e9f938f18aace0b
parenta2a0033acfff9b015de60ee138a08dd6370d6b07 (diff)
downloadopenssl-a8a21a6972394c2f76894dce5e0b882998b3f410.tar.gz
New ctrls to retrieve supported signature algorithms and curves and
extensions to s_client and s_server to print out retrieved valued. Extend CERT structure to cache supported signature algorithm data.
-rw-r--r--CHANGES5
-rw-r--r--apps/s_apps.h2
-rw-r--r--apps/s_cb.c71
-rw-r--r--apps/s_client.c2
-rw-r--r--apps/s_server.c5
-rw-r--r--ssl/s3_lib.c26
-rw-r--r--ssl/ssl.h6
-rw-r--r--ssl/ssl_cert.c5
-rw-r--r--ssl/ssl_locl.h19
-rw-r--r--ssl/t1_lib.c74
-rw-r--r--ssl/tls1.h6
11 files changed, 197 insertions, 24 deletions
diff --git a/CHANGES b/CHANGES
index 5dbdfc500..dc7636e4d 100644
--- a/CHANGES
+++ b/CHANGES
@@ -4,6 +4,11 @@
Changes between 1.0.1 and 1.1.0 [xx XXX xxxx]
+ *) New ctrls to retrieve supported signature algorithms and
+ supported curve values as an array of NIDs. Extend openssl utility
+ to print out received values.
+ [Steve Henson]
+
*) Add new APIs EC_curve_nist2nid and EC_curve_nid2nist which convert
between NIDs and the more common NIST names such as "P-256". Enhance
ecparam utility and ECC method to recognise the NIST names for curves.
diff --git a/apps/s_apps.h b/apps/s_apps.h
index 820e5c581..39a11d9a7 100644
--- a/apps/s_apps.h
+++ b/apps/s_apps.h
@@ -155,6 +155,8 @@ int MS_CALLBACK verify_callback(int ok, X509_STORE_CTX *ctx);
#ifdef HEADER_SSL_H
int set_cert_stuff(SSL_CTX *ctx, char *cert_file, char *key_file);
int set_cert_key_stuff(SSL_CTX *ctx, X509 *cert, EVP_PKEY *key);
+int ssl_print_sigalgs(BIO *out, SSL *s);
+int ssl_print_curves(BIO *out, SSL *s);
#endif
int init_client(int *sock, char *server, int port, int type);
int should_retry(int i);
diff --git a/apps/s_cb.c b/apps/s_cb.c
index 38eae7fe3..7eaffa8a5 100644
--- a/apps/s_cb.c
+++ b/apps/s_cb.c
@@ -278,6 +278,77 @@ int set_cert_key_stuff(SSL_CTX *ctx, X509 *cert, EVP_PKEY *key)
return 1;
}
+int ssl_print_sigalgs(BIO *out, SSL *s)
+ {
+ int i, nsig;
+ nsig = SSL_get_sigalgs(s, -1, NULL, NULL, NULL, NULL, NULL);
+ if (nsig == 0)
+ return 1;
+
+ BIO_puts(out, "Signature Algorithms: ");
+ for (i = 0; i < nsig; i++)
+ {
+ int hash_nid, sign_nid;
+ unsigned char rhash, rsign;
+ const char *sstr = NULL;
+ SSL_get_sigalgs(s, i, &sign_nid, &hash_nid, NULL,
+ &rsign, &rhash);
+ if (i)
+ BIO_puts(out, ":");
+ if (sign_nid == EVP_PKEY_RSA)
+ sstr = "RSA";
+ else if(sign_nid == EVP_PKEY_DSA)
+ sstr = "DSA";
+ else if(sign_nid == EVP_PKEY_EC)
+ sstr = "ECDSA";
+ if (sstr)
+ BIO_printf(out,"%s+", sstr);
+ else
+ BIO_printf(out,"0x%02X+", (int)rsign);
+ if (hash_nid != NID_undef)
+ BIO_printf(out, "%s", OBJ_nid2sn(hash_nid));
+ else
+ BIO_printf(out,"0x%02X", (int)rhash);
+ }
+ BIO_puts(out, "\n");
+ return 1;
+ }
+
+int ssl_print_curves(BIO *out, SSL *s)
+ {
+ int i, ncurves, *curves;
+ ncurves = SSL_get1_curvelist(s, NULL);
+ if (ncurves <= 0)
+ return 1;
+ curves = OPENSSL_malloc(ncurves * sizeof(int));
+ SSL_get1_curvelist(s, curves);
+
+ BIO_puts(out, "Supported Elliptic Curves: ");
+ for (i = 0; i < ncurves; i++)
+ {
+ int nid;
+ const char *cname;
+ if (i)
+ BIO_puts(out, ":");
+ nid = curves[i];
+ /* If unrecognised print out hex version */
+ if (nid & TLSEXT_nid_unknown)
+ BIO_printf(out, "0x%04X", nid & 0xFFFF);
+ else
+ {
+ /* Use NIST name for curve if it exists */
+ cname = EC_curve_nid2nist(nid);
+ if (!cname)
+ cname = OBJ_nid2sn(nid);
+ BIO_printf(out, "%s", cname);
+ }
+ }
+ BIO_puts(out, "\n");
+ OPENSSL_free(curves);
+ return 1;
+ }
+
+
long MS_CALLBACK bio_dump_callback(BIO *bio, int cmd, const char *argp,
int argi, long argl, long ret)
{
diff --git a/apps/s_client.c b/apps/s_client.c
index 7f389712d..ce199be81 100644
--- a/apps/s_client.c
+++ b/apps/s_client.c
@@ -2018,6 +2018,8 @@ static void print_stuff(BIO *bio, SSL *s, int full)
BIO_write(bio,"\n",1);
}
+ ssl_print_sigalgs(bio, s);
+
BIO_printf(bio,"---\nSSL handshake has read %ld bytes and written %ld bytes\n",
BIO_number_read(SSL_get_rbio(s)),
BIO_number_written(SSL_get_wbio(s)));
diff --git a/apps/s_server.c b/apps/s_server.c
index 1f4b85bb5..4603cdafc 100644
--- a/apps/s_server.c
+++ b/apps/s_server.c
@@ -2472,7 +2472,10 @@ static int init_ssl_connection(SSL *con)
if (SSL_get_shared_ciphers(con,buf,sizeof buf) != NULL)
BIO_printf(bio_s_out,"Shared ciphers:%s\n",buf);
str=SSL_CIPHER_get_name(SSL_get_current_cipher(con));
+ ssl_print_sigalgs(bio_s_out, con);
+ ssl_print_curves(bio_s_out, con);
BIO_printf(bio_s_out,"CIPHER is %s\n",(str != NULL)?str:"(NONE)");
+
#if !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_NEXTPROTONEG)
SSL_get0_next_proto_negotiated(con, &next_proto_neg, &next_proto_neg_len);
if (next_proto_neg)
@@ -2806,6 +2809,8 @@ static int www_body(char *hostname, int s, unsigned char *context)
}
BIO_puts(io,"\n");
}
+ ssl_print_sigalgs(io, con);
+ ssl_print_curves(io, con);
BIO_printf(io,(SSL_cache_hit(con)
?"---\nReused, "
:"---\nNew, "));
diff --git a/ssl/s3_lib.c b/ssl/s3_lib.c
index db79a99cc..248bb94df 100644
--- a/ssl/s3_lib.c
+++ b/ssl/s3_lib.c
@@ -3365,6 +3365,32 @@ long ssl3_ctrl(SSL *s, int cmd, long larg, void *parg)
else
return ssl_cert_add0_chain_cert(s->cert, (X509 *)parg);
+ case SSL_CTRL_GET_CURVELIST:
+ {
+ unsigned char *clist;
+ size_t clistlen;
+ if (!s->session)
+ return 0;
+ clist = s->session->tlsext_ellipticcurvelist;
+ clistlen = s->session->tlsext_ellipticcurvelist_length / 2;
+ if (parg)
+ {
+ size_t i;
+ int *cptr = parg;
+ unsigned int cid, nid;
+ for (i = 0; i < clistlen; i++)
+ {
+ n2s(clist, cid);
+ nid = tls1_ec_curve_id2nid(cid);
+ if (nid != 0)
+ cptr[i] = nid;
+ else
+ cptr[i] = TLSEXT_nid_unknown | cid;
+ }
+ }
+ return (int)clistlen;
+ }
+
default:
break;
}
diff --git a/ssl/ssl.h b/ssl/ssl.h
index 8998e9ad6..3e255fcfe 100644
--- a/ssl/ssl.h
+++ b/ssl/ssl.h
@@ -366,6 +366,7 @@ typedef struct tls_session_ticket_ext_st TLS_SESSION_TICKET_EXT;
typedef struct ssl_method_st SSL_METHOD;
typedef struct ssl_cipher_st SSL_CIPHER;
typedef struct ssl_session_st SSL_SESSION;
+typedef struct tls_sigalgs_st TLS_SIGALGS;
DECLARE_STACK_OF(SSL_CIPHER)
@@ -1617,6 +1618,8 @@ DECLARE_PEM_rw(SSL_SESSION, SSL_SESSION)
#define SSL_CTRL_CHAIN 88
#define SSL_CTRL_CHAIN_CERT 89
+#define SSL_CTRL_GET_CURVELIST 90
+
#define DTLSv1_get_timeout(ssl, arg) \
SSL_ctrl(ssl,DTLS_CTRL_GET_TIMEOUT,0, (void *)arg)
#define DTLSv1_handle_timeout(ssl) \
@@ -1675,6 +1678,9 @@ DECLARE_PEM_rw(SSL_SESSION, SSL_SESSION)
SSL_ctrl(ctx,SSL_CTRL_CHAIN_CERT,0,(char *)x509)
#define SSL_add1_chain_cert(ctx,x509) \
SSL_ctrl(ctx,SSL_CTRL_CHAIN_CERT,1,(char *)x509)
+#define SSL_get1_curvelist(ctx, s) \
+ SSL_ctrl(ctx,SSL_CTRL_GET_CURVELIST,0,(char *)s)
+
#ifndef OPENSSL_NO_BIO
BIO_METHOD *BIO_f_ssl(void);
diff --git a/ssl/ssl_cert.c b/ssl/ssl_cert.c
index c48aa2092..6a1c484fc 100644
--- a/ssl/ssl_cert.c
+++ b/ssl/ssl_cert.c
@@ -339,6 +339,9 @@ CERT *ssl_cert_dup(CERT *cert)
* will be set during handshake.
*/
ssl_cert_set_default_md(ret);
+ /* Sigalgs set to NULL as we get these from handshake too */
+ ret->sigalgs = NULL;
+ ret->sigalgslen = 0;
return(ret);
@@ -418,6 +421,8 @@ void ssl_cert_free(CERT *c)
EVP_PKEY_free(c->pkeys[i].publickey);
#endif
}
+ if (c->sigalgs)
+ OPENSSL_free(c->sigalgs);
OPENSSL_free(c);
}
diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h
index bdaca8bf4..ad5dc7104 100644
--- a/ssl/ssl_locl.h
+++ b/ssl/ssl_locl.h
@@ -506,6 +506,11 @@ typedef struct cert_st
CERT_PKEY pkeys[SSL_PKEY_NUM];
+ /* Array of pairs of NIDs for signature algorithm extension */
+ TLS_SIGALGS *sigalgs;
+ /* Size of above array */
+ size_t sigalgslen;
+
int references; /* >1 only if SSL_copy_session_id is used */
} CERT;
@@ -534,7 +539,19 @@ typedef struct sess_cert_st
int references; /* actually always 1 at the moment */
} SESS_CERT;
-
+/* Structure containing decoded values of signature algorithms extension */
+struct tls_sigalgs_st
+ {
+ /* NID of hash algorithm */
+ int hash_nid;
+ /* NID of signature algorithm */
+ int sign_nid;
+ /* Combined hash and signature NID */
+ int signandhash_nid;
+ /* Raw values used in extension */
+ unsigned char rsign;
+ unsigned char rhash;
+ };
/*#define MAC_DEBUG */
diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c
index 9c76da112..dfd397f9b 100644
--- a/ssl/t1_lib.c
+++ b/ssl/t1_lib.c
@@ -2241,32 +2241,18 @@ typedef struct
} tls12_lookup;
static tls12_lookup tls12_md[] = {
-#ifndef OPENSSL_NO_MD5
{NID_md5, TLSEXT_hash_md5},
-#endif
-#ifndef OPENSSL_NO_SHA
{NID_sha1, TLSEXT_hash_sha1},
-#endif
-#ifndef OPENSSL_NO_SHA256
{NID_sha224, TLSEXT_hash_sha224},
{NID_sha256, TLSEXT_hash_sha256},
-#endif
-#ifndef OPENSSL_NO_SHA512
{NID_sha384, TLSEXT_hash_sha384},
{NID_sha512, TLSEXT_hash_sha512}
-#endif
};
static tls12_lookup tls12_sig[] = {
-#ifndef OPENSSL_NO_RSA
{EVP_PKEY_RSA, TLSEXT_signature_rsa},
-#endif
-#ifndef OPENSSL_NO_RSA
{EVP_PKEY_DSA, TLSEXT_signature_dsa},
-#endif
-#ifndef OPENSSL_NO_ECDSA
{EVP_PKEY_EC, TLSEXT_signature_ecdsa}
-#endif
};
static int tls12_find_id(int nid, tls12_lookup *table, size_t tlen)
@@ -2279,18 +2265,17 @@ static int tls12_find_id(int nid, tls12_lookup *table, size_t tlen)
}
return -1;
}
-#if 0
+
static int tls12_find_nid(int id, tls12_lookup *table, size_t tlen)
{
size_t i;
for (i = 0; i < tlen; i++)
{
- if (table[i].id == id)
+ if ((table[i].id) == id)
return table[i].nid;
}
- return -1;
+ return NID_undef;
}
-#endif
int tls12_get_sigandhash(unsigned char *p, const EVP_PKEY *pk, const EVP_MD *md)
{
@@ -2358,6 +2343,7 @@ int tls1_process_sigalgs(SSL *s, const unsigned char *data, int dsize)
int i, idx;
const EVP_MD *md;
CERT *c = s->cert;
+ TLS_SIGALGS *sigptr;
/* Extension ignored for TLS versions below 1.2 */
if (TLS1_get_version(s) < TLS1_2_VERSION)
return 1;
@@ -2370,11 +2356,26 @@ int tls1_process_sigalgs(SSL *s, const unsigned char *data, int dsize)
c->pkeys[SSL_PKEY_RSA_ENC].digest = NULL;
c->pkeys[SSL_PKEY_ECC].digest = NULL;
- for (i = 0; i < dsize; i += 2)
- {
- unsigned char hash_alg = data[i], sig_alg = data[i+1];
+ if (c->sigalgs)
+ OPENSSL_free(c->sigalgs);
+ c->sigalgs = OPENSSL_malloc((dsize/2) * sizeof(TLS_SIGALGS));
+ if (!c->sigalgs)
+ return 0;
+ c->sigalgslen = dsize/2;
- switch(sig_alg)
+ for (i = 0, sigptr = c->sigalgs; i < dsize; i += 2, sigptr++)
+ {
+ sigptr->rhash = data[i];
+ sigptr->rsign = data[i + 1];
+ sigptr->hash_nid = tls12_find_nid(sigptr->rhash, tls12_md,
+ sizeof(tls12_md)/sizeof(tls12_lookup));
+ sigptr->sign_nid = tls12_find_nid(sigptr->rsign, tls12_sig,
+ sizeof(tls12_sig)/sizeof(tls12_lookup));
+ if (!OBJ_find_sigid_by_algs(&sigptr->signandhash_nid,
+ sigptr->hash_nid,
+ sigptr->sign_nid))
+ sigptr->signandhash_nid = NID_undef;
+ switch(sigptr->rsign)
{
#ifndef OPENSSL_NO_RSA
case TLSEXT_signature_rsa:
@@ -2397,7 +2398,7 @@ int tls1_process_sigalgs(SSL *s, const unsigned char *data, int dsize)
if (c->pkeys[idx].digest == NULL)
{
- md = tls12_get_hash(hash_alg);
+ md = tls12_get_hash(sigptr->rhash);
if (md)
{
c->pkeys[idx].digest = md;
@@ -2432,6 +2433,33 @@ int tls1_process_sigalgs(SSL *s, const unsigned char *data, int dsize)
#endif
+int SSL_get_sigalgs(SSL *s, int idx,
+ int *psign, int *phash, int *psignandhash,
+ unsigned char *rsig, unsigned char *rhash)
+ {
+ if (s->cert->sigalgs == NULL)
+ return 0;
+ if (idx >= 0)
+ {
+ TLS_SIGALGS *psig;
+ if (idx >= (int)s->cert->sigalgslen)
+ return 0;
+ psig = s->cert->sigalgs + idx;
+ if (psign)
+ *psign = psig->sign_nid;
+ if (phash)
+ *phash = psig->hash_nid;
+ if (psignandhash)
+ *psignandhash = psig->signandhash_nid;
+ if (rsig)
+ *rsig = psig->rsign;
+ if (rhash)
+ *rhash = psig->rhash;
+ }
+ return s->cert->sigalgslen;
+ }
+
+
#ifndef OPENSSL_NO_HEARTBEATS
int
tls1_process_heartbeat(SSL *s)
diff --git a/ssl/tls1.h b/ssl/tls1.h
index c5e3a7002..cca04b874 100644
--- a/ssl/tls1.h
+++ b/ssl/tls1.h
@@ -252,6 +252,8 @@ extern "C" {
#define TLSEXT_hash_sha256 4
#define TLSEXT_hash_sha384 5
#define TLSEXT_hash_sha512 6
+/* Flag set for unrecognised algorithms */
+#define TLSEXT_nid_unknown 0x1000000
/* ExtensionType value from RFC5764 */
#define TLSEXT_TYPE_use_srtp 14
@@ -276,6 +278,10 @@ int SSL_export_keying_material(SSL *s, unsigned char *out, size_t olen,
const char *label, size_t llen, const unsigned char *p, size_t plen,
int use_context);
+int SSL_get_sigalgs(SSL *s, int idx,
+ int *psign, int *phash, int *psignandhash,
+ unsigned char *rsig, unsigned char *rhash);
+
#define SSL_set_tlsext_host_name(s,name) \
SSL_ctrl(s,SSL_CTRL_SET_TLSEXT_HOSTNAME,TLSEXT_NAMETYPE_host_name,(char *)name)