Store table entry to peer signature algorithm.
authorDr. Stephen Henson <steve@openssl.org>
Mon, 30 Jan 2017 13:48:39 +0000 (13:48 +0000)
committerDr. Stephen Henson <steve@openssl.org>
Tue, 31 Jan 2017 00:02:59 +0000 (00:02 +0000)
Reviewed-by: Rich Salz <rsalz@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/2324)

ssl/s3_lib.c
ssl/ssl_locl.h
ssl/t1_lib.c

index 936a301..df9d0c7 100644 (file)
@@ -3177,20 +3177,10 @@ long ssl3_ctrl(SSL *s, int cmd, long larg, void *parg)
         return ssl_cert_set_cert_store(s->cert, parg, 1, larg);
 
     case SSL_CTRL_GET_PEER_SIGNATURE_NID:
-        if (SSL_USE_SIGALGS(s)) {
-            if (s->session) {
-                const EVP_MD *sig;
-                sig = s->s3->tmp.peer_md;
-                if (sig) {
-                    *(int *)parg = EVP_MD_type(sig);
-                    return 1;
-                }
-            }
-            return 0;
-        }
-        /* Might want to do something here for other versions */
-        else
+        if (s->s3->tmp.peer_sigalg == NULL)
             return 0;
+        *(int *)parg = s->s3->tmp.peer_sigalg->hash;
+        return 1;
 
     case SSL_CTRL_GET_SERVER_TMP_KEY:
 #if !defined(OPENSSL_NO_DH) || !defined(OPENSSL_NO_EC)
index 13be4f3..c2139cb 100644 (file)
@@ -1180,6 +1180,25 @@ struct ssl_st {
     CRYPTO_RWLOCK *lock;
 };
 
+/*
+ * Structure containing table entry of values associated with the signature
+ * algorithms (signature scheme) extension
+*/
+typedef struct sigalg_lookup_st {
+    /* TLS 1.3 signature scheme name */
+    const char *name;
+    /* Raw value used in extension */
+    uint16_t sigalg;
+    /* NID of hash algorithm */
+    int hash;
+    /* NID of signature algorithm */
+    int sig;
+    /* Combined hash and signature NID, if any */
+    int sigandhash;
+    /* Required public key curve (ECDSA only) */
+    int curve;
+} SIGALG_LOOKUP;
+
 typedef struct ssl3_state_st {
     long flags;
     size_t read_mac_secret_size;
@@ -1269,10 +1288,10 @@ typedef struct ssl3_state_st {
         uint16_t *peer_sigalgs;
         /* Size of above array */
         size_t peer_sigalgslen;
+        /* Sigalg peer actualy uses */
+        const SIGALG_LOOKUP *peer_sigalg;
         /* Digest peer uses for signing */
         const EVP_MD *peer_md;
-        /* Signature type: public key type or EVP_PKEY_RSA_PSS for PSS */
-        int peer_sigtype;
         /* Array of digests used for signing */
         const EVP_MD *md[SSL_PKEY_NUM];
         /*
@@ -1509,25 +1528,6 @@ typedef struct {
     size_t meths_count;
 } custom_ext_methods;
 
-/*
- * Structure containing table entry of values associated with the signature
- * algorithms (signature scheme) extension
-*/
-typedef struct sigalg_lookup_st {
-    /* TLS 1.3 signature scheme name */
-    const char *name;
-    /* Raw value used in extension */
-    uint16_t sigalg;
-    /* NID of hash algorithm */
-    int hash;
-    /* NID of signature algorithm */
-    int sig;
-    /* Combined hash and signature NID, if any */
-    int sigandhash;
-    /* Required public key curve (ECDSA only) */
-    int curve;
-} SIGALG_LOOKUP;
-
 typedef struct cert_st {
     /* Current active set */
     /*
@@ -1750,7 +1750,8 @@ typedef enum tlsext_index_en {
 /* An invalid index into the TLSv1.3 PSK identities */
 #define TLSEXT_PSK_BAD_IDENTITY                                 -1
 
-#define SSL_USE_PSS(s) (s->s3->tmp.peer_sigtype == EVP_PKEY_RSA_PSS)
+#define SSL_USE_PSS(s) (s->s3->tmp.peer_sigalg != NULL && \
+                        s->s3->tmp.peer_sigalg->sig == EVP_PKEY_RSA_PSS)
 
 /* A dummy signature value not valid for TLSv1.2 signature algs */
 #define TLSEXT_signature_rsa_pss                                0x0101
@@ -2260,7 +2261,7 @@ __owur int tls12_copy_sigalgs(SSL *s, WPACKET *pkt,
 __owur int tls1_save_sigalgs(SSL *s, PACKET *pkt);
 __owur int tls1_process_sigalgs(SSL *s);
 __owur size_t tls12_get_psigalgs(SSL *s, int sent, const uint16_t **psigs);
-__owur int tls12_check_peer_sigalg(SSL *s, unsigned int sig, EVP_PKEY *pkey);
+__owur int tls12_check_peer_sigalg(SSL *s, uint16_t, EVP_PKEY *pkey);
 void ssl_set_client_disabled(SSL *s);
 __owur int ssl_cipher_disabled(SSL *s, const SSL_CIPHER *c, int op);
 
index c906061..2a39e7e 100644 (file)
@@ -823,23 +823,25 @@ size_t tls12_get_psigalgs(SSL *s, int sent, const uint16_t **psigs)
  * algorithms and if so set relevant digest and signature scheme in
  * s.
  */
-int tls12_check_peer_sigalg(SSL *s, unsigned int sig, EVP_PKEY *pkey)
+int tls12_check_peer_sigalg(SSL *s, uint16_t sig, EVP_PKEY *pkey)
 {
     const uint16_t *sent_sigs;
     const EVP_MD *md = NULL;
     char sigalgstr[2];
     size_t sent_sigslen, i;
     int pkeyid = EVP_PKEY_id(pkey);
-    int peer_sigtype;
+    const SIGALG_LOOKUP *lu;
 
     /* Should never happen */
     if (pkeyid == -1)
         return -1;
-    /* Check key type is consistent with signature */
-    peer_sigtype = tls_sigalg_get_sig(sig);
-    /* RSA keys can be used for RSA-PSS */
-    if (pkeyid != peer_sigtype
-        && (peer_sigtype != EVP_PKEY_RSA_PSS || pkeyid != EVP_PKEY_RSA)) {
+    lu = tls1_lookup_sigalg(sig);
+    /*
+     * Check sigalgs is known and key type is consistent with signature:
+     * RSA keys can be used for RSA-PSS
+     */
+    if (lu == NULL || (pkeyid != lu->sig
+        && (lu->sig != EVP_PKEY_RSA_PSS || pkeyid != EVP_PKEY_RSA))) {
         SSLerr(SSL_F_TLS12_CHECK_PEER_SIGALG, SSL_R_WRONG_SIGNATURE_TYPE);
         return 0;
     }
@@ -883,13 +885,12 @@ int tls12_check_peer_sigalg(SSL *s, unsigned int sig, EVP_PKEY *pkey)
             break;
     }
     /* Allow fallback to SHA1 if not strict mode */
-    if (i == sent_sigslen
-        && (tls_sigalg_get_hash(sig) != NID_sha1
-            || s->cert->cert_flags & SSL_CERT_FLAGS_CHECK_TLS_STRICT)) {
+    if (i == sent_sigslen && (lu->hash != NID_sha1
+        || s->cert->cert_flags & SSL_CERT_FLAGS_CHECK_TLS_STRICT)) {
         SSLerr(SSL_F_TLS12_CHECK_PEER_SIGALG, SSL_R_WRONG_SIGNATURE_TYPE);
         return 0;
     }
-    md = tls12_get_hash(tls_sigalg_get_hash(sig));
+    md = tls12_get_hash(lu->hash);
     if (md == NULL) {
         SSLerr(SSL_F_TLS12_CHECK_PEER_SIGALG, SSL_R_UNKNOWN_DIGEST);
         return 0;
@@ -910,15 +911,15 @@ int tls12_check_peer_sigalg(SSL *s, unsigned int sig, EVP_PKEY *pkey)
      * Store the digest used so applications can retrieve it if they wish.
      */
     s->s3->tmp.peer_md = md;
-    s->s3->tmp.peer_sigtype = peer_sigtype;
+    s->s3->tmp.peer_sigalg = lu;
     return 1;
 }
 
 int SSL_get_peer_signature_type_nid(const SSL *s, int *pnid)
 {
-    if (s->s3->tmp.peer_sigtype == NID_undef)
+    if (s->s3->tmp.peer_sigalg == NULL)
         return 0;
-    *pnid = s->s3->tmp.peer_sigtype;
+    *pnid = s->s3->tmp.peer_sigalg->sig;
     return 1;
 }