From dcc956872958ec62352d422d394d509c43ffdd32 Mon Sep 17 00:00:00 2001 From: Nikos Mavrogiannopoulos Date: Tue, 8 Aug 2017 11:35:26 +0200 Subject: gnutls_certificate_credentials_t: combine privkey into cert_st structure This reduces the number of applications and allows for easier use of the structure information, as they are now self-contained for most uses. Signed-off-by: Nikos Mavrogiannopoulos --- lib/auth/cert.c | 8 ++-- lib/auth/cert.h | 16 ++------ lib/cert.c | 14 ++----- lib/x509.c | 119 +++++++++++++++++++++++--------------------------------- 4 files changed, 61 insertions(+), 96 deletions(-) diff --git a/lib/auth/cert.c b/lib/auth/cert.c index c66f4f2950..5fd2286266 100644 --- a/lib/auth/cert.c +++ b/lib/auth/cert.c @@ -596,7 +596,7 @@ select_client_cert(gnutls_session_t session, cert_list[0], cred->certs[indx]. cert_list_length, - cred->pkey[indx], 0, + cred->certs[indx].pkey, 0, NULL, NULL); } else { _gnutls_selected_certs_set(session, NULL, 0, NULL, 0, @@ -1567,7 +1567,7 @@ _gnutls_server_select_cert(gnutls_session_t session, const gnutls_cipher_suite_e ret = select_sign_algorithm(session, &cred->certs[i].cert_list[0], - cred->pkey[i], + cred->certs[i].pkey, cs); if (ret >= 0) { idx = i; @@ -1604,7 +1604,7 @@ _gnutls_server_select_cert(gnutls_session_t session, const gnutls_cipher_suite_e ret = select_sign_algorithm(session, &cred->certs[i].cert_list[0], - cred->pkey[i], + cred->certs[i].pkey, cs); if (ret >= 0) { idx = i; @@ -1626,7 +1626,7 @@ _gnutls_server_select_cert(gnutls_session_t session, const gnutls_cipher_suite_e _gnutls_selected_certs_set(session, &cred->certs[idx].cert_list[0], cred->certs[idx].cert_list_length, - cred->pkey[idx], 0, + cred->certs[idx].pkey, 0, cred->certs[idx].ocsp_func, cred->certs[idx].ocsp_func_ptr); } else { diff --git a/lib/auth/cert.h b/lib/auth/cert.h index 2d72762722..be6945dd21 100644 --- a/lib/auth/cert.h +++ b/lib/auth/cert.h @@ -1,5 +1,6 @@ /* * Copyright (C) 2002-2012 Free Software Foundation, Inc. + * Copyright (C) 2016-2017 Red Hat, Inc. * * Author: Nikos Mavrogiannopoulos * @@ -37,6 +38,9 @@ typedef struct { gnutls_status_request_ocsp_func ocsp_func; void *ocsp_func_ptr; /* corresponding OCSP response function + ptr */ char *ocsp_response_file; /* corresponding OCSP response file */ + + /* the private key corresponding to certificate */ + gnutls_privkey_t pkey; } certs_st; /* This structure may be complex, but it's the only way to @@ -55,12 +59,6 @@ typedef struct gnutls_certificate_credentials_st { certs_st *certs; unsigned ncerts; /* the number of certs */ - gnutls_privkey_t *pkey; - /* private keys. It contains ncerts private - * keys. pkey[i] corresponds to certificate in - * cert_list[i][0]. - */ - /* X509 specific stuff */ gnutls_x509_trust_list_t tlist; unsigned flags; /* gnutls_certificate_flags */ @@ -133,12 +131,6 @@ int _gnutls_get_auth_info_pcert(gnutls_pcert_st * gcert, gnutls_certificate_type_t type, cert_auth_info_t info); -int certificate_credential_append_crt_list(gnutls_certificate_credentials_t - res, gnutls_str_array_t names, - gnutls_pcert_st * crt, int nr); -int certificate_credentials_append_pkey(gnutls_certificate_credentials_t - res, gnutls_privkey_t pkey); - int _gnutls_selected_cert_supported_kx(struct gnutls_session_int *session, gnutls_kx_algorithm_t * alg, int *alg_size); diff --git a/lib/cert.c b/lib/cert.c index b53ad21fb1..4defec87e2 100644 --- a/lib/cert.c +++ b/lib/cert.c @@ -1,6 +1,6 @@ /* * Copyright (C) 2001-2016 Free Software Foundation, Inc. - * Copyright (C) 2015-2016 Red Hat, Inc. + * Copyright (C) 2015-2017 Red Hat, Inc. * * Author: Nikos Mavrogiannopoulos * @@ -62,18 +62,12 @@ void gnutls_certificate_free_keys(gnutls_certificate_credentials_t sc) gnutls_free(sc->certs[i].cert_list); gnutls_free(sc->certs[i].ocsp_response_file); _gnutls_str_array_clear(&sc->certs[i].names); + gnutls_privkey_deinit(sc->certs[i].pkey); } gnutls_free(sc->certs); sc->certs = NULL; - for (i = 0; i < sc->ncerts; i++) { - gnutls_privkey_deinit(sc->pkey[i]); - } - - gnutls_free(sc->pkey); - sc->pkey = NULL; - sc->ncerts = 0; } @@ -684,7 +678,7 @@ int _gnutls_check_key_cert_match(gnutls_certificate_credentials_t res) gnutls_pubkey_get_pk_algorithm(res->certs[res->ncerts - 1]. cert_list[0].pubkey, NULL); pk2 = - gnutls_privkey_get_pk_algorithm(res->pkey[res->ncerts - 1], + gnutls_privkey_get_pk_algorithm(res->certs[res->ncerts - 1].pkey, NULL); if (GNUTLS_PK_IS_RSA(pk) && GNUTLS_PK_IS_RSA(pk2)) { @@ -707,7 +701,7 @@ int _gnutls_check_key_cert_match(gnutls_certificate_credentials_t res) /* now check if keys really match. We use the sign/verify approach * because we cannot always obtain the parameters from the abstract * keys (e.g. PKCS #11). */ - ret = gnutls_privkey_sign_data2(res->pkey[res->ncerts - 1], + ret = gnutls_privkey_sign_data2(res->certs[res->ncerts - 1].pkey, sign_algo, 0, &test, &sig); if (ret < 0) { /* for some reason we couldn't sign that. That shouldn't have diff --git a/lib/x509.c b/lib/x509.c index 3e64fb14a8..d1171dc7c7 100644 --- a/lib/x509.c +++ b/lib/x509.c @@ -1,6 +1,6 @@ /* * Copyright (C) 2002-2016 Free Software Foundation, Inc. - * Copyright (C) 2016 Red Hat, Inc. + * Copyright (C) 2016-2017 Red Hat, Inc. * * Author: Nikos Mavrogiannopoulos * @@ -56,6 +56,12 @@ * some x509 certificate parsing functions. */ +static int +certificate_credential_append_crt_list(gnutls_certificate_credentials_t res, + gnutls_privkey_t key, + gnutls_str_array_t names, + gnutls_pcert_st * crt, int nr); + #define CRED_RET_SUCCESS(cred) \ if (cred->flags & GNUTLS_CERTIFICATE_API_V2) { \ return cred->ncerts-1; \ @@ -475,6 +481,7 @@ static int get_x509_name(gnutls_x509_crt_t crt, gnutls_str_array_t * names) */ static int parse_der_cert_mem(gnutls_certificate_credentials_t res, + gnutls_privkey_t key, const void *input_cert, int input_cert_size) { gnutls_datum_t tmp; @@ -522,7 +529,7 @@ parse_der_cert_mem(gnutls_certificate_credentials_t res, goto cleanup; } - ret = certificate_credential_append_crt_list(res, names, ccert, 1); + ret = certificate_credential_append_crt_list(res, key, names, ccert, 1); if (ret < 0) { gnutls_assert(); goto cleanup; @@ -541,6 +548,7 @@ parse_der_cert_mem(gnutls_certificate_credentials_t res, */ static int parse_pem_cert_mem(gnutls_certificate_credentials_t res, + gnutls_privkey_t key, const char *input_cert, int input_cert_size) { int size; @@ -637,7 +645,7 @@ parse_pem_cert_mem(gnutls_certificate_credentials_t res, } ret = - certificate_credential_append_crt_list(res, names, pcerts, + certificate_credential_append_crt_list(res, key, names, pcerts, ncerts); if (ret < 0) { gnutls_assert(); @@ -666,15 +674,17 @@ parse_pem_cert_mem(gnutls_certificate_credentials_t res, /* Reads a DER or PEM certificate from memory */ static int -read_cert_mem(gnutls_certificate_credentials_t res, const void *cert, +read_cert_mem(gnutls_certificate_credentials_t res, + gnutls_privkey_t key, + const void *cert, int cert_size, gnutls_x509_crt_fmt_t type) { int ret; if (type == GNUTLS_X509_FMT_DER) - ret = parse_der_cert_mem(res, cert, cert_size); + ret = parse_der_cert_mem(res, key, cert, cert_size); else - ret = parse_pem_cert_mem(res, cert, cert_size); + ret = parse_pem_cert_mem(res, key, cert, cert_size); if (ret < 0) { gnutls_assert(); @@ -699,13 +709,15 @@ static int tmp_pin_cb(void *userdata, int attempt, const char *token_url, } /* Reads a PEM encoded PKCS-1 RSA/DSA private key from memory. Type - * indicates the certificate format. KEY can be NULL, to indicate - * that GnuTLS doesn't know the private key. + * indicates the certificate format. + * + * It returns the private key read in @rkey. */ static int read_key_mem(gnutls_certificate_credentials_t res, const void *key, int key_size, gnutls_x509_crt_fmt_t type, - const char *pass, unsigned int flags) + const char *pass, unsigned int flags, + gnutls_privkey_t *rkey) { int ret; gnutls_datum_t tmp; @@ -742,19 +754,12 @@ read_key_mem(gnutls_certificate_credentials_t res, return ret; } - ret = certificate_credentials_append_pkey(res, privkey); - if (ret < 0) { - gnutls_assert(); - gnutls_privkey_deinit(privkey); - return ret; - } - + *rkey = privkey; } else { gnutls_assert(); return GNUTLS_E_INVALID_REQUEST; } - return 0; } @@ -762,7 +767,7 @@ read_key_mem(gnutls_certificate_credentials_t res, /* Reads a private key from a token. */ static int -read_key_url(gnutls_certificate_credentials_t res, const char *url) +read_key_url(gnutls_certificate_credentials_t res, const char *url, gnutls_privkey_t *rkey) { int ret; gnutls_privkey_t pkey = NULL; @@ -785,11 +790,7 @@ read_key_url(gnutls_certificate_credentials_t res, const char *url) goto cleanup; } - ret = certificate_credentials_append_pkey(res, pkey); - if (ret < 0) { - gnutls_assert(); - goto cleanup; - } + *rkey = pkey; return 0; @@ -805,7 +806,7 @@ read_key_url(gnutls_certificate_credentials_t res, const char *url) /* Reads a certificate key from a token. */ static int -read_cert_url(gnutls_certificate_credentials_t res, const char *url) +read_cert_url(gnutls_certificate_credentials_t res, gnutls_privkey_t key, const char *url) { int ret; gnutls_x509_crt_t crt = NULL; @@ -885,7 +886,7 @@ read_cert_url(gnutls_certificate_credentials_t res, const char *url) t.data = NULL; } - ret = certificate_credential_append_crt_list(res, names, ccert, count); + ret = certificate_credential_append_crt_list(res, key, names, ccert, count); if (ret < 0) { gnutls_assert(); goto cleanup; @@ -908,6 +909,7 @@ cleanup: */ static int read_cert_file(gnutls_certificate_credentials_t res, + gnutls_privkey_t key, const char *certfile, gnutls_x509_crt_fmt_t type) { int ret; @@ -915,7 +917,7 @@ read_cert_file(gnutls_certificate_credentials_t res, char *data; if (gnutls_url_is_supported(certfile)) { - return read_cert_url(res, certfile); + return read_cert_url(res, key, certfile); } data = read_binary_file(certfile, &size); @@ -925,7 +927,7 @@ read_cert_file(gnutls_certificate_credentials_t res, return GNUTLS_E_FILE_ERROR; } - ret = read_cert_mem(res, data, size, type); + ret = read_cert_mem(res, key, data, size, type); free(data); return ret; @@ -940,7 +942,8 @@ read_cert_file(gnutls_certificate_credentials_t res, static int read_key_file(gnutls_certificate_credentials_t res, const char *keyfile, gnutls_x509_crt_fmt_t type, - const char *pass, unsigned int flags) + const char *pass, unsigned int flags, + gnutls_privkey_t *rkey) { int ret; size_t size; @@ -955,7 +958,7 @@ read_key_file(gnutls_certificate_credentials_t res, gnutls_certificate_set_pin_function(res, tmp_pin_cb, res->pin_tmp); } - return read_key_url(res, keyfile); + return read_key_url(res, keyfile, rkey); } else return gnutls_assert_val @@ -969,7 +972,7 @@ read_key_file(gnutls_certificate_credentials_t res, return GNUTLS_E_FILE_ERROR; } - ret = read_key_mem(res, data, size, type, pass, flags); + ret = read_key_mem(res, data, size, type, pass, flags, rkey); free(data); return ret; @@ -1052,16 +1055,17 @@ gnutls_certificate_set_x509_key_mem2(gnutls_certificate_credentials_t res, const char *pass, unsigned int flags) { int ret; + gnutls_privkey_t rkey; /* this should be first */ if ((ret = read_key_mem(res, key ? key->data : NULL, key ? key->size : 0, type, pass, - flags)) < 0) + flags, &rkey)) < 0) return ret; - if ((ret = read_cert_mem(res, cert->data, cert->size, type)) < 0) { - gnutls_privkey_deinit(res->pkey[res->ncerts]); + if ((ret = read_cert_mem(res, rkey, cert->data, cert->size, type)) < 0) { + gnutls_privkey_deinit(rkey); return ret; } @@ -1075,9 +1079,10 @@ gnutls_certificate_set_x509_key_mem2(gnutls_certificate_credentials_t res, CRED_RET_SUCCESS(res); } -int -certificate_credential_append_crt_list(gnutls_certificate_credentials_t - res, gnutls_str_array_t names, +static int +certificate_credential_append_crt_list(gnutls_certificate_credentials_t res, + gnutls_privkey_t key, + gnutls_str_array_t names, gnutls_pcert_st * crt, int nr) { res->certs = gnutls_realloc_fast(res->certs, @@ -1093,27 +1098,12 @@ certificate_credential_append_crt_list(gnutls_certificate_credentials_t res->certs[res->ncerts].cert_list = crt; res->certs[res->ncerts].cert_list_length = nr; res->certs[res->ncerts].names = names; + res->certs[res->ncerts].pkey = key; return 0; } -int -certificate_credentials_append_pkey(gnutls_certificate_credentials_t res, - gnutls_privkey_t pkey) -{ - res->pkey = gnutls_realloc_fast(res->pkey, - (1 + res->ncerts) * - sizeof(gnutls_privkey_t)); - if (res->pkey == NULL) { - gnutls_assert(); - return GNUTLS_E_MEMORY_ERROR; - } - res->pkey[res->ncerts] = pkey; - return 0; - -} - /** * gnutls_certificate_set_x509_key: * @res: is a #gnutls_certificate_credentials_t type. @@ -1175,12 +1165,6 @@ gnutls_certificate_set_x509_key(gnutls_certificate_credentials_t res, return ret; } - ret = certificate_credentials_append_pkey(res, pkey); - if (ret < 0) { - gnutls_assert(); - return ret; - } - /* load certificates */ pcerts = gnutls_malloc(sizeof(gnutls_pcert_st) * cert_list_size); if (pcerts == NULL) { @@ -1203,7 +1187,7 @@ gnutls_certificate_set_x509_key(gnutls_certificate_credentials_t res, } ret = - certificate_credential_append_crt_list(res, names, pcerts, + certificate_credential_append_crt_list(res, pkey, names, pcerts, cert_list_size); if (ret < 0) { gnutls_assert(); @@ -1263,7 +1247,7 @@ gnutls_certificate_get_x509_key(gnutls_certificate_credentials_t res, return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; } - return gnutls_privkey_export_x509(res->pkey[index], key); + return gnutls_privkey_export_x509(res->certs[index].pkey, key); } /** @@ -1415,12 +1399,6 @@ gnutls_certificate_set_key(gnutls_certificate_credentials_t res, gnutls_privkey_set_pin_function(key, res->pin.cb, res->pin.data); - ret = certificate_credentials_append_pkey(res, key); - if (ret < 0) { - gnutls_assert(); - goto cleanup; - } - new_pcert_list = gnutls_malloc(sizeof(gnutls_pcert_st) * pcert_list_size); if (new_pcert_list == NULL) { gnutls_assert(); @@ -1429,7 +1407,7 @@ gnutls_certificate_set_key(gnutls_certificate_credentials_t res, memcpy(new_pcert_list, pcert_list, sizeof(gnutls_pcert_st) * pcert_list_size); ret = - certificate_credential_append_crt_list(res, str_names, + certificate_credential_append_crt_list(res, key, str_names, new_pcert_list, pcert_list_size); if (ret < 0) { @@ -1599,15 +1577,16 @@ gnutls_certificate_set_x509_key_file2(gnutls_certificate_credentials_t res, const char *pass, unsigned int flags) { int ret; + gnutls_privkey_t rkey; /* this should be first */ - if ((ret = read_key_file(res, keyfile, type, pass, flags)) < 0) + if ((ret = read_key_file(res, keyfile, type, pass, flags, &rkey)) < 0) return ret; - if ((ret = read_cert_file(res, certfile, type)) < 0) { - gnutls_privkey_deinit(res->pkey[res->ncerts]); + if ((ret = read_cert_file(res, rkey, certfile, type)) < 0) { + gnutls_privkey_deinit(rkey); return ret; } -- cgit v1.2.1