]> git.ipfire.org Git - thirdparty/openssl.git/blobdiff - ssl/ssl_cert.c
first cut at sigalg loading
[thirdparty/openssl.git] / ssl / ssl_cert.c
index 320f6d322ec486c03bb6b4b77dd9d89778d70956..1c4f452997ae46eb7b8332c78540933db1e0c47d 100644 (file)
@@ -58,13 +58,25 @@ int SSL_get_ex_data_X509_STORE_CTX_idx(void)
     return ssl_x509_store_ctx_idx;
 }
 
-CERT *ssl_cert_new(void)
+CERT *ssl_cert_new(size_t ssl_pkey_num)
 {
-    CERT *ret = OPENSSL_zalloc(sizeof(*ret));
+    CERT *ret = NULL;
+
+    /* Should never happen */
+    if (!ossl_assert(ssl_pkey_num >= SSL_PKEY_NUM))
+        return NULL;
 
+    ret = OPENSSL_zalloc(sizeof(*ret));
     if (ret == NULL)
         return NULL;
 
+    ret->ssl_pkey_num = ssl_pkey_num;
+    ret->pkeys = OPENSSL_zalloc(ret->ssl_pkey_num * sizeof(CERT_PKEY));
+    if (ret->pkeys == NULL) {
+        OPENSSL_free(ret);
+        return NULL;
+    }
+
     ret->key = &(ret->pkeys[SSL_PKEY_RSA]);
     ret->references = 1;
     ret->sec_cb = ssl_security_default_callback;
@@ -73,6 +85,7 @@ CERT *ssl_cert_new(void)
     ret->lock = CRYPTO_THREAD_lock_new();
     if (ret->lock == NULL) {
         ERR_raise(ERR_LIB_SSL, ERR_R_CRYPTO_LIB);
+        OPENSSL_free(ret->pkeys);
         OPENSSL_free(ret);
         return NULL;
     }
@@ -83,7 +96,7 @@ CERT *ssl_cert_new(void)
 CERT *ssl_cert_dup(CERT *cert)
 {
     CERT *ret = OPENSSL_zalloc(sizeof(*ret));
-    int i;
+    size_t i;
 #ifndef OPENSSL_NO_COMP_ALG
     int j;
 #endif
@@ -91,6 +104,11 @@ CERT *ssl_cert_dup(CERT *cert)
     if (ret == NULL)
         return NULL;
 
+    ret->ssl_pkey_num = cert->ssl_pkey_num;
+    ret->pkeys = OPENSSL_zalloc(ret->ssl_pkey_num * sizeof(CERT_PKEY));
+    if (ret->pkeys == NULL)
+        return NULL;
+
     ret->references = 1;
     ret->key = &ret->pkeys[cert->key - cert->pkeys];
     ret->lock = CRYPTO_THREAD_lock_new();
@@ -108,7 +126,7 @@ CERT *ssl_cert_dup(CERT *cert)
     ret->dh_tmp_cb = cert->dh_tmp_cb;
     ret->dh_tmp_auto = cert->dh_tmp_auto;
 
-    for (i = 0; i < SSL_PKEY_NUM; i++) {
+    for (i = 0; i < ret->ssl_pkey_num; i++) {
         CERT_PKEY *cpk = cert->pkeys + i;
         CERT_PKEY *rpk = ret->pkeys + i;
 
@@ -217,14 +235,14 @@ CERT *ssl_cert_dup(CERT *cert)
 
 void ssl_cert_clear_certs(CERT *c)
 {
-    int i;
+    size_t i;
 #ifndef OPENSSL_NO_COMP_ALG
     int j;
 #endif
     
     if (c == NULL)
         return;
-    for (i = 0; i < SSL_PKEY_NUM; i++) {
+    for (i = 0; i < c->ssl_pkey_num; i++) {
         CERT_PKEY *cpk = c->pkeys + i;
         X509_free(cpk->x509);
         cpk->x509 = NULL;
@@ -269,6 +287,7 @@ void ssl_cert_free(CERT *c)
 #ifndef OPENSSL_NO_PSK
     OPENSSL_free(c->psk_identity_hint);
 #endif
+    OPENSSL_free(c->pkeys);
     CRYPTO_THREAD_lock_free(c->lock);
     OPENSSL_free(c);
 }
@@ -297,6 +316,7 @@ int ssl_cert_set0_chain(SSL_CONNECTION *s, SSL_CTX *ctx, STACK_OF(X509) *chain)
 int ssl_cert_set1_chain(SSL_CONNECTION *s, SSL_CTX *ctx, STACK_OF(X509) *chain)
 {
     STACK_OF(X509) *dchain;
+
     if (!chain)
         return ssl_cert_set0_chain(s, ctx, NULL);
     dchain = X509_chain_up_ref(chain);
@@ -313,6 +333,7 @@ int ssl_cert_add0_chain_cert(SSL_CONNECTION *s, SSL_CTX *ctx, X509 *x)
 {
     int r;
     CERT_PKEY *cpk = s ? s->cert->key : ctx->cert->key;
+
     if (!cpk)
         return 0;
     r = ssl_security_cert(s, ctx, x, 0, 0);
@@ -337,10 +358,11 @@ int ssl_cert_add1_chain_cert(SSL_CONNECTION *s, SSL_CTX *ctx, X509 *x)
 
 int ssl_cert_select_current(CERT *c, X509 *x)
 {
-    int i;
+    size_t i;
+
     if (x == NULL)
         return 0;
-    for (i = 0; i < SSL_PKEY_NUM; i++) {
+    for (i = 0; i < c->ssl_pkey_num; i++) {
         CERT_PKEY *cpk = c->pkeys + i;
         if (cpk->x509 == x && cpk->privatekey) {
             c->key = cpk;
@@ -348,7 +370,7 @@ int ssl_cert_select_current(CERT *c, X509 *x)
         }
     }
 
-    for (i = 0; i < SSL_PKEY_NUM; i++) {
+    for (i = 0; i < c->ssl_pkey_num; i++) {
         CERT_PKEY *cpk = c->pkeys + i;
         if (cpk->privatekey && cpk->x509 && !X509_cmp(cpk->x509, x)) {
             c->key = cpk;
@@ -360,18 +382,19 @@ int ssl_cert_select_current(CERT *c, X509 *x)
 
 int ssl_cert_set_current(CERT *c, long op)
 {
-    int i, idx;
+    size_t i, idx;
+
     if (!c)
         return 0;
     if (op == SSL_CERT_SET_FIRST)
         idx = 0;
     else if (op == SSL_CERT_SET_NEXT) {
-        idx = (int)(c->key - c->pkeys + 1);
-        if (idx >= SSL_PKEY_NUM)
+        idx = (size_t)(c->key - c->pkeys + 1);
+        if (idx >= c->ssl_pkey_num)
             return 0;
     } else
         return 0;
-    for (i = idx; i < SSL_PKEY_NUM; i++) {
+    for (i = idx; i < c->ssl_pkey_num; i++) {
         CERT_PKEY *cpk = c->pkeys + i;
         if (cpk->x509 && cpk->privatekey) {
             c->key = cpk;
@@ -1156,7 +1179,7 @@ int ssl_ctx_security(const SSL_CTX *ctx, int op, int bits, int nid, void *other)
                              ctx->cert->sec_ex);
 }
 
-int ssl_cert_lookup_by_nid(int nid, size_t *pidx)
+int ssl_cert_lookup_by_nid(int nid, size_t *pidx, SSL_CTX *ctx)
 {
     size_t i;
 
@@ -1166,16 +1189,22 @@ int ssl_cert_lookup_by_nid(int nid, size_t *pidx)
             return 1;
         }
     }
-
+    for (i = 0; i < ctx->sigalg_list_len; i++) {
+        if (ctx->ssl_cert_info[i].nid == nid) {
+            *pidx = SSL_PKEY_NUM + i;
+            return 1;
+        }
+    }
     return 0;
 }
 
-const SSL_CERT_LOOKUP *ssl_cert_lookup_by_pkey(const EVP_PKEY *pk, size_t *pidx)
+SSL_CERT_LOOKUP *ssl_cert_lookup_by_pkey(const EVP_PKEY *pk, size_t *pidx, SSL_CTX *ctx)
 {
     size_t i;
 
+    /* check classic pk types */
     for (i = 0; i < OSSL_NELEM(ssl_cert_info); i++) {
-        const SSL_CERT_LOOKUP *tmp_lu = &ssl_cert_info[i];
+        SSL_CERT_LOOKUP *tmp_lu = &ssl_cert_info[i];
 
         if (EVP_PKEY_is_a(pk, OBJ_nid2sn(tmp_lu->nid))
             || EVP_PKEY_is_a(pk, OBJ_nid2ln(tmp_lu->nid))) {
@@ -1184,13 +1213,26 @@ const SSL_CERT_LOOKUP *ssl_cert_lookup_by_pkey(const EVP_PKEY *pk, size_t *pidx)
             return tmp_lu;
         }
     }
+    /* check provider-loaded pk types */
+    for (i = 0; ctx->sigalg_list_len; i++) {
+        SSL_CERT_LOOKUP *tmp_lu = &(ctx->ssl_cert_info[i]);
+
+        if (EVP_PKEY_is_a(pk, OBJ_nid2sn(tmp_lu->nid))
+            || EVP_PKEY_is_a(pk, OBJ_nid2ln(tmp_lu->nid))) {
+            if (pidx != NULL)
+                *pidx = SSL_PKEY_NUM + i;
+            return &ctx->ssl_cert_info[i];
+        }
+    }
 
     return NULL;
 }
 
-const SSL_CERT_LOOKUP *ssl_cert_lookup_by_idx(size_t idx)
+SSL_CERT_LOOKUP *ssl_cert_lookup_by_idx(size_t idx, SSL_CTX *ctx)
 {
-    if (idx >= OSSL_NELEM(ssl_cert_info))
+    if (idx >= (OSSL_NELEM(ssl_cert_info) + ctx->sigalg_list_len))
         return NULL;
+    else if (idx >= (OSSL_NELEM(ssl_cert_info)))
+        return &(ctx->ssl_cert_info[idx - SSL_PKEY_NUM]);
     return &ssl_cert_info[idx];
 }