From: Nikos Mavrogiannopoulos Date: Thu, 18 Dec 2003 10:32:36 +0000 (+0000) Subject: Added the callbacks gnutls_certificate_client_retrieve_function() and X-Git-Tag: gnutls_1_1_0~17 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=4d4fa5bb8a4e2c2fb1fc9ab68a4d6b887e497aa7;p=thirdparty%2Fgnutls.git Added the callbacks gnutls_certificate_client_retrieve_function() and gnutls_certificate_server_retrieve_function(), to allow a client or a server to specify certificates for the handshake without storing them to the credentials structure. --- diff --git a/NEWS b/NEWS index d23d93efe6..512b3a4e7f 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,10 @@ Version 1.1.0 - The error codes GNUTLS_E_NO_TEMPORARY_DH_PARAMS and GNUTLS_E_NO_TEMPORARY_RSA_PARAMS are no longer returned by the handshake function. Ciphersuites that require temporary parameters are removed when such parameters do not exist. +- Added the callbacks gnutls_certificate_client_retrieve_function() and + gnutls_certificate_server_retrieve_function(), to allow a client or a server + to specify certificates for the handshake without storing them to the + credentials structure. Version 1.0.1 (10/12/2003) - Some minor fixes in the makefiles. They now include CFLAGS diff --git a/lib/auth_cert.c b/lib/auth_cert.c index 9a99c3948b..08d5c99260 100644 --- a/lib/auth_cert.c +++ b/lib/auth_cert.c @@ -44,12 +44,18 @@ #include #include "debug.h" +static gnutls_cert *alloc_and_load_certs(const gnutls_datum * certs, + uint ncerts, gnutls_certificate_type type); +static gnutls_privkey *alloc_and_load_key(const gnutls_datum * raw_key, + gnutls_certificate_type type); + + /* Copies data from a internal certificate struct (gnutls_cert) to * exported certificate struct (CERTIFICATE_AUTH_INFO) */ static -int _gnutls_copy_certificate_auth_info(CERTIFICATE_AUTH_INFO info, - gnutls_cert * cert, int ncerts) +int _gnutls_copy_certificate_auth_info(CERTIFICATE_AUTH_INFO info, + gnutls_cert * cert, int ncerts) { /* Copy peer's information to AUTH_INFO */ @@ -60,7 +66,7 @@ int _gnutls_copy_certificate_auth_info(CERTIFICATE_AUTH_INFO info, info->ncerts = 0; return 0; } - + info->raw_certificate_list = gnutls_calloc(1, sizeof(gnutls_datum) * ncerts); if (info->raw_certificate_list == NULL) { @@ -146,7 +152,9 @@ static int _find_x509_cert(const gnutls_certificate_credentials cred, for (i = 0; i < cred->ncerts; i++) { for (j = 0; j < cred->cert_list_length[i]; j++) { if ((result = - _gnutls_cert_get_dn( &cred->cert_list[i][j], &odn)) < 0) { + _gnutls_cert_get_dn(&cred-> + cert_list[i][j], + &odn)) < 0) { gnutls_assert(); return result; } @@ -158,10 +166,14 @@ static int _find_x509_cert(const gnutls_certificate_credentials cred, * the *_SIGN algorithm matches * the cert is our cert! */ - cert_pk = cred->cert_list[i][0].subject_pk_algorithm; + cert_pk = + cred->cert_list[i][0]. + subject_pk_algorithm; if ((memcmp(odn.data, data, size) == 0) && - (_gnutls_check_pk_algo_in_list(pk_algos, pk_algos_length, cert_pk) == 0)) { + (_gnutls_check_pk_algo_in_list + (pk_algos, pk_algos_length, + cert_pk) == 0)) { *indx = i; break; } @@ -215,9 +227,213 @@ static int _find_openpgp_cert(const gnutls_certificate_credentials cred, return 0; } -/* Some upper limit to protect alloca(); +/* Returns the number of issuers in the server's + * certificate request packet. + */ +static int get_issuers_num( gnutls_session session, opaque * data, ssize_t data_size) +{ +int issuers_dn_len, result; +uint size; + + /* Count the number of the given issuers; + * This is used to allocate the issuers_dn without + * using realloc(). + */ + + if (gnutls_certificate_type_get(session) != GNUTLS_CRT_X509) + return 0; + + do { + /* This works like DECR_LEN() + */ + result = GNUTLS_E_UNEXPECTED_PACKET_LENGTH; + DECR_LENGTH_COM(data_size, 2, goto error); + size = _gnutls_read_uint16(data); + + result = GNUTLS_E_UNEXPECTED_PACKET_LENGTH; + DECR_LENGTH_COM(data_size, size, goto error); + + data += 2; + + if (size > 0) { + issuers_dn_len++; + data += size; + } + + if (data_size == 0) + break; + + } while (1); + + return issuers_dn_len; + + error: + return result; +} + +/* Returns the issuers in the server's certificate request + * packet. + */ +static int get_issuers( gnutls_session session, + gnutls_datum* issuers_dn, int issuers_len, + opaque * data, size_t data_size) +{ +int i; +uint size; + + if (gnutls_certificate_type_get(session) != GNUTLS_CRT_X509) + return 0; + + /* put the requested DNs to req_dn, only in case + * of X509 certificates. + */ + if (issuers_len > 0) { + + for (i = 0; i < issuers_len; i++) { + /* The checks here for the buffer boundaries + * are not needed since the buffer has been + * parsed above. + */ + data_size -= 2; + + size = _gnutls_read_uint16(data); + + data += 2; + + issuers_dn[i].data = data; + issuers_dn[i].size = size; + + data += size; + } + } + + return 0; +} + + +/* Calls the client_cert_callback() to select an index for the + * certificate to use. + */ +static int call_client_cert_callback(gnutls_session session, + const gnutls_certificate_credentials cred, gnutls_pk_algorithm * pk_algos, + int pk_algos_length, gnutls_datum * issuers_dn, uint issuers_dn_len) +{ + uint i, j; + int indx, result; + int *ij_map = NULL; + gnutls_datum *my_certs = NULL; + + if (cred->ncerts != 0) { + my_certs = + gnutls_alloca(cred->ncerts * + sizeof(gnutls_datum)); + if (my_certs == NULL) { + result = GNUTLS_E_MEMORY_ERROR; + gnutls_assert(); + goto error; + } + + + /* maps j -> i + */ + ij_map = gnutls_alloca(sizeof(int) * cred->ncerts); + if (ij_map == NULL) { + result = GNUTLS_E_MEMORY_ERROR; + gnutls_assert(); + goto error; + } + } + + /* put our certificate's issuer and dn into cdn, idn + * Note that the certificates we provide to the callback + * are not all the certificates we have. Only the certificates + * that are requested by the server (certificate type - and sign + * algorithm matches), are provided. + */ + for (j = i = 0; i < cred->ncerts; i++) { + if ((cred->cert_list[i][0].cert_type == + gnutls_certificate_type_get(session)) && + (_gnutls_check_pk_algo_in_list(pk_algos, + pk_algos_length, + cred-> + cert_list[i][0]. + subject_pk_algorithm) + == 0)) { + /* Add a certificate ONLY if it is allowed + * by the peer. + */ + ij_map[j] = i; + my_certs[j++] = cred->cert_list[i][0].raw; + } + } + + indx = + session->internals.client_cert_callback(session, + my_certs, + j, + issuers_dn, + issuers_dn_len); + + /* the indx returned by the user is relative + * to the certificates we provided him. + * This will make it relative to the certificates + * we've got. + */ + if (indx != -1 && cred->ncerts != 0) + indx = ij_map[indx]; + else + indx = -1; + + + result = indx; + + error: + if (my_certs != NULL) { + gnutls_afree(my_certs); + } + if (ij_map != NULL) { + gnutls_afree(ij_map); + } + return result; + +} + +/* Calls the client get callback. */ -#define MAX_ISSUERS 512 +static int call_client_get_cert_callback( gnutls_session session, + gnutls_datum* issuers_dn, int issuers_dn_length) +{ +gnutls_datum *certs, key; +uint ncerts, i; +gnutls_certificate_type type = + gnutls_certificate_type_get(session); +gnutls_cert *local_certs = NULL; +gnutls_privkey *local_key = NULL; +int ret; + + ret = + session->internals.client_get_cert_callback(session, + issuers_dn, issuers_dn_length, + &certs, &ncerts, &key); + if (ret < 0) { + gnutls_assert(); + return GNUTLS_E_INTERNAL_ERROR; + } + + local_certs = alloc_and_load_certs(certs, ncerts, type); + if (local_certs != NULL) + local_key = alloc_and_load_key(&key, type); + + for (i = 0; i < ncerts; i++) { + _gnutls_free_datum(&certs[i]); + } + _gnutls_free_datum(&key); + + _gnutls_selected_certs_set(session, local_certs, ncerts, + local_key, 1); + + return 0; +} /* Finds the appropriate certificate depending on the cA Distinguished name * advertized by the server. If none matches then returns 0 and -1 as index. @@ -227,18 +443,17 @@ static int _find_openpgp_cert(const gnutls_certificate_credentials cred, * algorithm (only in automatic mode). */ static int _select_client_cert(gnutls_session session, - opaque * _data, size_t _data_size, int *ind, - gnutls_pk_algorithm *pk_algos, int pk_algos_length) + opaque * _data, size_t _data_size, + gnutls_pk_algorithm * pk_algos, + int pk_algos_length) { - int result, size; + int result; int indx = -1; - uint i, j; - int *ij_map = NULL; const gnutls_certificate_credentials cred; opaque *data = _data; ssize_t data_size = _data_size; - gnutls_datum *my_certs = NULL; - gnutls_datum *issuers_dn = NULL; + int issuers_dn_length; + gnutls_datum * issuers_dn = NULL; cred = _gnutls_get_cred(session->key, GNUTLS_CRD_CERTIFICATE, NULL); @@ -247,9 +462,44 @@ static int _select_client_cert(gnutls_session session, return GNUTLS_E_INSUFFICIENT_CREDENTIALS; } - /* If we have no callback. - */ - if (session->internals.client_cert_callback == NULL) { + if (session->internals.client_get_cert_callback != NULL || + session->internals.client_cert_callback != NULL) { + + /* use a callback to get certificate + */ + issuers_dn_length = get_issuers_num( session, data, data_size); + if (issuers_dn_length < 0) { + gnutls_assert(); + return issuers_dn_length; + } + + if (issuers_dn_length > 0) { + issuers_dn = gnutls_malloc( sizeof(gnutls_datum)*issuers_dn_length); + if (issuers_dn == NULL) { + gnutls_assert(); + return GNUTLS_E_MEMORY_ERROR; + } + + result = get_issuers( session, issuers_dn, issuers_dn_length, data, data_size); + if (result < 0) { + gnutls_assert(); + goto cleanup; + } + } + + if (session->internals.client_get_cert_callback) { + result = call_client_get_cert_callback( session, issuers_dn, issuers_dn_length); + goto cleanup; + } + + /* in case of the callback that returns an index: + */ + indx = call_client_cert_callback(session, cred, pk_algos, + pk_algos_length, issuers_dn, issuers_dn_length); + + } else { + /* If we have no callbacks, try to guess. + */ result = 0; if (session->security_parameters.cert_type == @@ -270,162 +520,22 @@ static int _select_client_cert(gnutls_session session, gnutls_assert(); return result; } - } else /* If the callback is set, then use it. */ - if (session->internals.client_cert_callback != NULL) { - /* use a callback to get certificate - */ - uint issuers_dn_len = 0; - opaque *dataptr = data; - ssize_t dataptr_size = data_size; - - /* Count the number of the given issuers; - * This is used to allocate the issuers_dn without - * using realloc(). - */ - - if (gnutls_certificate_type_get(session) == GNUTLS_CRT_X509) { - - /* Makes the issuers_dn stuff. - */ - do { - /* This works like DECR_LEN() - */ - result = GNUTLS_E_UNEXPECTED_PACKET_LENGTH; - DECR_LENGTH_COM(dataptr_size, 2, goto error); - size = _gnutls_read_uint16(dataptr); - - result = GNUTLS_E_UNEXPECTED_PACKET_LENGTH; - DECR_LENGTH_COM(dataptr_size, size, goto error); - - dataptr += 2; - - if (size > 0) { - issuers_dn_len++; - dataptr += size; - } - - if (dataptr_size == 0) - break; - - } while (issuers_dn_len < MAX_ISSUERS); - - if (cred->ncerts != 0) { - my_certs = - gnutls_alloca(cred->ncerts * sizeof(gnutls_datum)); - if (my_certs == NULL) { - result = GNUTLS_E_MEMORY_ERROR; - gnutls_assert(); - goto error; - } - } - - /* put the requested DNs to req_dn, only in case - * of X509 certificates. - */ - if (issuers_dn_len > 0) { - data = _data; - data_size = _data_size; - - issuers_dn = - gnutls_alloca(issuers_dn_len * - sizeof(gnutls_datum)); - if (issuers_dn == NULL) { - result = GNUTLS_E_MEMORY_ERROR; - gnutls_assert(); - goto error; - } - - for (i = 0; i < issuers_dn_len; i++) { - /* The checks here for the buffer boundaries - * are not needed since the buffer has been - * parsed above. - */ - data_size -= 2; - - size = _gnutls_read_uint16(data); - - data += 2; - - issuers_dn[i].data = data; - issuers_dn[i].size = size; - - data += size; - - } - } - - } else { /* Other certificate types */ - issuers_dn_len = 0; - issuers_dn = NULL; - } - - /* If not certificates are present. - */ - /* maps j -> i - */ - - if (cred->ncerts != 0) { - ij_map = gnutls_alloca(sizeof(int) * cred->ncerts); - if (ij_map == NULL) { - result = GNUTLS_E_MEMORY_ERROR; - gnutls_assert(); - goto error; - } - } - - /* put our certificate's issuer and dn into cdn, idn - * Note that the certificates we provide to the callback - * are not all the certificates we have. Only the certificates - * that are requested by the server (certificate type - and sign - * algorithm matches), are provided. - */ - for (j = i = 0; i < cred->ncerts; i++) { - if ((cred->cert_list[i][0].cert_type == - gnutls_certificate_type_get(session)) && - (_gnutls_check_pk_algo_in_list(pk_algos, - pk_algos_length, - cred-> - cert_list[i][0]. - subject_pk_algorithm) - == 0)) { - /* Add a certificate ONLY if it is allowed - * by the peer. - */ - ij_map[j] = i; - my_certs[j++] = cred->cert_list[i][0].raw; - } - } - - indx = - session->internals.client_cert_callback(session, - my_certs, - j, - issuers_dn, - issuers_dn_len); - - /* the indx returned by the user is relative - * to the certificates we provided him. - * This will make it relative to the certificates - * we've got. - */ - if (indx != -1 && cred->ncerts != 0) - indx = ij_map[indx]; - else - indx = -1; + } - if (my_certs) { gnutls_afree(my_certs); } - if (ij_map) { gnutls_afree(ij_map); } - if (issuers_dn) { gnutls_afree(issuers_dn); } + if (indx >= 0) { + _gnutls_selected_certs_set(session, + &cred->cert_list[indx][0], + cred->cert_list_length[indx], + &cred->pkey[indx], 0); + } else { + _gnutls_selected_certs_set(session, NULL, 0, NULL, 0); } - *ind = indx; - return 0; + result = 0; - error: - if (my_certs != NULL) { gnutls_afree(my_certs); } - if (ij_map != NULL) { gnutls_afree(ij_map); } - if (issuers_dn != NULL) { gnutls_afree(issuers_dn); } - return result; +cleanup: + gnutls_free( issuers_dn); + return result; } @@ -444,8 +554,8 @@ int _gnutls_gen_x509_crt(gnutls_session session, opaque ** data) */ if ((ret = _gnutls_get_selected_cert(session, &apr_cert_list, - &apr_cert_list_length, - &apr_pkey)) < 0) { + &apr_cert_list_length, + &apr_pkey)) < 0) { gnutls_assert(); return ret; } @@ -490,14 +600,14 @@ int _gnutls_gen_openpgp_certificate(gnutls_session session, opaque ** data) int ret; opaque *pdata; gnutls_cert *apr_cert_list; - gnutls_privkey* apr_pkey; + gnutls_privkey *apr_pkey; int apr_cert_list_length; /* find the appropriate certificate */ if ((ret = _gnutls_get_selected_cert(session, &apr_cert_list, - &apr_cert_list_length, - &apr_pkey)) < 0) { + &apr_cert_list_length, + &apr_pkey)) < 0) { gnutls_assert(); return ret; } @@ -541,14 +651,14 @@ int _gnutls_gen_openpgp_certificate_fpr(gnutls_session session, size_t fpr_size; opaque *pdata; gnutls_cert *apr_cert_list; - gnutls_privkey* apr_pkey; + gnutls_privkey *apr_pkey; int apr_cert_list_length; /* find the appropriate certificate */ if ((ret = _gnutls_get_selected_cert(session, &apr_cert_list, - &apr_cert_list_length, - &apr_pkey)) < 0) { + &apr_cert_list_length, + &apr_pkey)) < 0) { gnutls_assert(); return ret; } @@ -637,7 +747,7 @@ int _gnutls_gen_cert_server_certificate(gnutls_session session, /* Process server certificate */ -#define CLEAR_CERTS for(x=0;x= 0) { - session->internals.selected_cert_list_length = cred->cert_list_length[ind]; - session->internals.selected_cert_list = &cred->cert_list[ind][0]; - session->internals.selected_key = &cred->pkey[ind]; - } else { - session->internals.selected_cert_list_length = 0; - session->internals.selected_cert_list = NULL; - session->internals.selected_key = NULL; - } /* We should reply with a certificate message, * even if we have no certificate to send. @@ -1064,7 +1165,7 @@ int _gnutls_gen_cert_client_cert_vrfy(gnutls_session session, { int ret; gnutls_cert *apr_cert_list; - gnutls_privkey* apr_pkey; + gnutls_privkey *apr_pkey; int apr_cert_list_length, size; gnutls_datum signature; @@ -1073,8 +1174,8 @@ int _gnutls_gen_cert_client_cert_vrfy(gnutls_session session, /* find the appropriate certificate */ if ((ret = _gnutls_get_selected_cert(session, &apr_cert_list, - &apr_cert_list_length, - &apr_pkey)) < 0) { + &apr_cert_list_length, + &apr_pkey)) < 0) { gnutls_assert(); return ret; } @@ -1082,9 +1183,8 @@ int _gnutls_gen_cert_client_cert_vrfy(gnutls_session session, if (apr_pkey != NULL) { if ((ret = _gnutls_tls_sign_hdata(session, - &apr_cert_list[0], - apr_pkey, - &signature)) < 0) { + &apr_cert_list[0], + apr_pkey, &signature)) < 0) { gnutls_assert(); return ret; } @@ -1165,10 +1265,10 @@ int _gnutls_proc_cert_client_cert_vrfy(gnutls_session session, if ((ret = _gnutls_verify_sig_hdata(session, &peer_cert, &sig)) < 0) { gnutls_assert(); - _gnutls_free_cert(&peer_cert); + _gnutls_cert_deinit(&peer_cert); return ret; } - _gnutls_free_cert(&peer_cert); + _gnutls_cert_deinit(&peer_cert); return 0; } @@ -1197,7 +1297,7 @@ int _gnutls_gen_cert_server_cert_req(gnutls_session session, */ if (session->security_parameters.cert_type == GNUTLS_CRT_X509 && - session->internals.ignore_rdn_sequence == 0) + session->internals.ignore_rdn_sequence == 0) size += cred->x509_rdn_sequence.size; (*data) = gnutls_malloc(size); @@ -1215,7 +1315,7 @@ int _gnutls_gen_cert_server_cert_req(gnutls_session session, pdata += CERTTYPE_SIZE; if (session->security_parameters.cert_type == GNUTLS_CRT_X509 && - session->internals.ignore_rdn_sequence == 0) { + session->internals.ignore_rdn_sequence == 0) { _gnutls_write_datum16(pdata, cred->x509_rdn_sequence); /* pdata += cred->x509_rdn_sequence.size + 2; */ } @@ -1232,9 +1332,9 @@ int _gnutls_gen_cert_server_cert_req(gnutls_session session, * */ int _gnutls_get_selected_cert(gnutls_session session, - gnutls_cert ** apr_cert_list, - int *apr_cert_list_length, - gnutls_privkey ** apr_pkey) + gnutls_cert ** apr_cert_list, + int *apr_cert_list_length, + gnutls_privkey ** apr_pkey) { if (session->security_parameters.entity == GNUTLS_SERVER) { @@ -1243,23 +1343,24 @@ int _gnutls_get_selected_cert(gnutls_session session, *apr_cert_list = session->internals.selected_cert_list; *apr_pkey = session->internals.selected_key; - *apr_cert_list_length = session->internals.selected_cert_list_length; + *apr_cert_list_length = + session->internals.selected_cert_list_length; - if ( apr_cert_list_length == 0 || apr_pkey == NULL || - apr_cert_list == NULL) - { + if (apr_cert_list_length == 0 || apr_pkey == NULL || + apr_cert_list == NULL) { gnutls_assert(); return GNUTLS_E_INSUFFICIENT_CREDENTIALS; } - } else { /* CLIENT SIDE - */ + } else { /* CLIENT SIDE + */ /* we have already decided which certificate * to send. */ *apr_cert_list = session->internals.selected_cert_list; - *apr_cert_list_length = session->internals.selected_cert_list_length; + *apr_cert_list_length = + session->internals.selected_cert_list_length; *apr_pkey = session->internals.selected_key; } @@ -1267,6 +1368,102 @@ int _gnutls_get_selected_cert(gnutls_session session, return 0; } +/* converts the given raw certificate to gnutls_cert* and allocates + * space for them. + */ +static gnutls_cert *alloc_and_load_certs(const gnutls_datum * certs, + uint ncerts, + gnutls_certificate_type type) +{ + gnutls_cert *local_certs; + int ret = 0; + uint i, j; + + local_certs = gnutls_malloc(sizeof(gnutls_cert) * ncerts); + if (local_certs == NULL) { + gnutls_assert(); + return NULL; + } + + for (i = 0; i < ncerts; i++) { + ret = _gnutls_cert2gnutls_cert(&local_certs[i], type, + &certs[i], 0); + if (ret < 0) + break; + } + + if (ret < 0) { + gnutls_assert(); + for (j = 0; j < i; j++) { + _gnutls_cert_deinit(&local_certs[j]); + } + gnutls_free(local_certs); + return NULL; + } + + return local_certs; +} + +/* converts the given raw key to gnutls_privkey* and allocates + * space for it. + */ +static gnutls_privkey *alloc_and_load_key(const gnutls_datum * raw_key, + gnutls_certificate_type type) +{ + gnutls_privkey *local_key; + int ret = 0; + + local_key = gnutls_malloc(sizeof(gnutls_privkey)); + if (local_key == NULL) { + gnutls_assert(); + return NULL; + } + + ret = + _gnutls_key2gnutls_key(local_key, type, raw_key, + GNUTLS_X509_FMT_DER); + if (ret < 0) { + gnutls_assert(); + return NULL; + } + + return local_key; +} + +void _gnutls_selected_certs_deinit(gnutls_session session) +{ + if (session->internals.selected_need_free != 0) { + int i; + + for (i = 0; + i < session->internals.selected_cert_list_length; + i++) { + _gnutls_cert_deinit(&session->internals. + selected_cert_list[i]); + } + session->internals.selected_cert_list = NULL; + session->internals.selected_cert_list_length = 0; + + _gnutls_privkey_deinit(session->internals.selected_key); + } + + return; +} + +void _gnutls_selected_certs_set(gnutls_session session, + gnutls_cert * certs, int ncerts, + gnutls_privkey * key, int need_free) +{ + _gnutls_selected_certs_deinit(session); + + session->internals.selected_cert_list = certs; + session->internals.selected_cert_list_length = ncerts; + session->internals.selected_key = key; + session->internals.selected_need_free = need_free; + +} + + /* finds the most appropriate certificate in the cert list. * The 'appropriate' is defined by the user. * @@ -1278,7 +1475,7 @@ int _gnutls_get_selected_cert(gnutls_session session, * */ int _gnutls_server_select_cert(gnutls_session session, - gnutls_pk_algorithm requested_algo) + gnutls_pk_algorithm requested_algo) { uint i, j; int index, ret; @@ -1311,7 +1508,43 @@ int _gnutls_server_select_cert(gnutls_session session, } - if (session->internals.server_cert_callback != NULL && cred->ncerts > 0) { + /* If the callback which retrieves certificate has been + * set use it. + */ + if (session->internals.server_get_cert_callback != NULL) { + gnutls_datum *certs, key; + uint ncerts; + gnutls_certificate_type type = + gnutls_certificate_type_get(session); + gnutls_cert *local_certs = NULL; + gnutls_privkey *local_key = NULL; + + ret = + session->internals.server_get_cert_callback(session, + &certs, + &ncerts, + &key); + if (ret < 0) { + gnutls_assert(); + return GNUTLS_E_INTERNAL_ERROR; + } + + local_certs = alloc_and_load_certs(certs, ncerts, type); + if (local_certs != NULL) + local_key = alloc_and_load_key(&key, type); + + for (i = 0; i < ncerts; i++) { + _gnutls_free_datum(&certs[i]); + } + _gnutls_free_datum(&key); + + _gnutls_selected_certs_set(session, local_certs, ncerts, + local_key, 1); + + return 0; + + } else if (session->internals.server_cert_callback != NULL + && cred->ncerts > 0) { /* use the callback to get certificate */ gnutls_datum *my_certs; @@ -1363,19 +1596,20 @@ int _gnutls_server_select_cert(gnutls_session session, ret = 0; gnutls_free(ij_map); - cleanup_certs: + cleanup_certs: gnutls_free(my_certs); } - out: + out: /* store the index for future use, in the handshake. * (This will allow not calling this callback again.) */ if (index >= 0 && ret == 0) { - session->internals.selected_cert_list = &cred->cert_list[index][0]; - session->internals.selected_cert_list_length = cred->cert_list_length[index]; - session->internals.selected_key = &cred->pkey[index]; + _gnutls_selected_certs_set(session, + &cred->cert_list[index][0], + cred->cert_list_length[index], + &cred->pkey[index], 0); } return ret; diff --git a/lib/auth_cert.h b/lib/auth_cert.h index 8f58018cb9..94085ca53d 100644 --- a/lib/auth_cert.h +++ b/lib/auth_cert.h @@ -92,6 +92,10 @@ int _gnutls_proc_cert_server_certificate(gnutls_session, opaque *, size_t); int _gnutls_get_selected_cert( gnutls_session session, gnutls_cert** apr_cert_list, int *apr_cert_list_length, gnutls_privkey** apr_pkey); int _gnutls_server_select_cert( struct gnutls_session_int*, gnutls_pk_algorithm); +void _gnutls_selected_certs_deinit( gnutls_session session); +void _gnutls_selected_certs_set( gnutls_session session, + gnutls_cert* certs, int ncerts, gnutls_privkey* key, + int need_free); #define _gnutls_proc_cert_client_certificate _gnutls_proc_cert_server_certificate diff --git a/lib/auth_dhe.c b/lib/auth_dhe.c index bf636df2d2..885a8a9aca 100644 --- a/lib/auth_dhe.c +++ b/lib/auth_dhe.c @@ -171,9 +171,6 @@ static int gen_dhe_server_kx(gnutls_session session, opaque ** data) return data_size; } - -OPENPGP_CERT2GNUTLS_CERT _E_gnutls_openpgp_cert2gnutls_cert = NULL; - static int proc_dhe_server_kx(gnutls_session session, opaque * data, size_t _data_size) { @@ -208,32 +205,11 @@ static int proc_dhe_server_kx(gnutls_session session, opaque * data, signature.data = &data[vparams.size + 2]; signature.size = sigsize; - switch( session->security_parameters.cert_type) { - case GNUTLS_CRT_X509: - if ((ret = - _gnutls_x509_cert2gnutls_cert( &peer_cert, - &info->raw_certificate_list[0], CERT_NO_COPY)) < 0) { - gnutls_assert(); - return ret; - } - break; - - case GNUTLS_CRT_OPENPGP: - if (_E_gnutls_openpgp_cert2gnutls_cert==NULL) { - gnutls_assert(); - return GNUTLS_E_INIT_LIBEXTRA; - } - if ((ret = - _E_gnutls_openpgp_cert2gnutls_cert( &peer_cert, - &info->raw_certificate_list[0])) < 0) { - gnutls_assert(); - return ret; - } - break; - - default: - gnutls_assert(); - return GNUTLS_E_INTERNAL_ERROR; + if ((ret = + _gnutls_cert2gnutls_cert( &peer_cert, session->security_parameters.cert_type, + &info->raw_certificate_list[0], CERT_NO_COPY)) < 0) { + gnutls_assert(); + return ret; } ret = @@ -241,7 +217,7 @@ static int proc_dhe_server_kx(gnutls_session session, opaque * data, &peer_cert, &vparams, &signature); - _gnutls_free_cert( &peer_cert); + _gnutls_cert_deinit( &peer_cert); if (ret < 0) { gnutls_assert(); return ret; diff --git a/lib/auth_rsa.c b/lib/auth_rsa.c index 8dd219716e..8be77e7e9e 100644 --- a/lib/auth_rsa.c +++ b/lib/auth_rsa.c @@ -60,9 +60,6 @@ const MOD_AUTH_STRUCT rsa_auth_struct = { _gnutls_proc_cert_cert_req /* proc server cert request */ }; -/* in auth_dhe.c */ -extern OPENPGP_CERT2GNUTLS_CERT _E_gnutls_openpgp_cert2gnutls_cert; - /* This function reads the RSA parameters from peer's certificate; */ int _gnutls_get_public_rsa_params(gnutls_session session, @@ -82,32 +79,13 @@ int i; return GNUTLS_E_INTERNAL_ERROR; } - switch( session->security_parameters.cert_type) { - case GNUTLS_CRT_X509: - if ((ret = - _gnutls_x509_cert2gnutls_cert( &peer_cert, - &info->raw_certificate_list[0], CERT_ONLY_PUBKEY|CERT_NO_COPY)) < 0) { - gnutls_assert(); - return ret; - } - break; - - case GNUTLS_CRT_OPENPGP: - if (_E_gnutls_openpgp_cert2gnutls_cert==NULL) { - gnutls_assert(); - return GNUTLS_E_INIT_LIBEXTRA; - } - if ((ret = - _E_gnutls_openpgp_cert2gnutls_cert( &peer_cert, - &info->raw_certificate_list[0])) < 0) { - gnutls_assert(); - return ret; - } - break; - - default: + ret = + _gnutls_cert2gnutls_cert( &peer_cert, session->security_parameters.cert_type, + &info->raw_certificate_list[0], CERT_ONLY_PUBKEY|CERT_NO_COPY); + + if (ret < 0) { gnutls_assert(); - return GNUTLS_E_INTERNAL_ERROR; + return ret; } @@ -116,7 +94,7 @@ int i; == GNUTLS_KX_RSA_EXPORT && _gnutls_mpi_get_nbits(peer_cert.params[0]) > 512) { - _gnutls_free_cert( &peer_cert); + _gnutls_cert_deinit( &peer_cert); if (session->key->rsa[0] == NULL || session->key->rsa[1] == NULL) { @@ -147,7 +125,7 @@ int i; for (i=0;i<*params_len;i++) { params[i] = _gnutls_mpi_copy(peer_cert.params[i]); } - _gnutls_free_cert( &peer_cert); + _gnutls_cert_deinit( &peer_cert); return 0; } diff --git a/lib/auth_rsa_export.c b/lib/auth_rsa_export.c index 9d61d63e6b..902e970061 100644 --- a/lib/auth_rsa_export.c +++ b/lib/auth_rsa_export.c @@ -64,9 +64,6 @@ const MOD_AUTH_STRUCT rsa_export_auth_struct = { _gnutls_proc_cert_cert_req /* proc server cert request */ }; -extern OPENPGP_CERT2GNUTLS_CERT _E_gnutls_openpgp_cert2gnutls_cert; - - static int gen_rsa_export_server_kx(gnutls_session session, opaque ** data) { const GNUTLS_MPI *rsa_params; @@ -191,47 +188,26 @@ CERTIFICATE_AUTH_INFO info = _gnutls_get_auth_info( session); return 0; } - switch( session->security_parameters.cert_type) { - case GNUTLS_CRT_X509: - if ((ret = - _gnutls_x509_cert2gnutls_cert( &peer_cert, - &info->raw_certificate_list[0], CERT_NO_COPY)) < 0) { - gnutls_assert(); - return 0; - } - break; - - case GNUTLS_CRT_OPENPGP: - if (_E_gnutls_openpgp_cert2gnutls_cert==NULL) { - gnutls_assert(); - return GNUTLS_E_INIT_LIBEXTRA; - } - if ((ret = - _E_gnutls_openpgp_cert2gnutls_cert( &peer_cert, - &info->raw_certificate_list[0])) < 0) { - gnutls_assert(); - return 0; - } - break; - - default: - gnutls_assert(); - return 0; + if ((ret = + _gnutls_cert2gnutls_cert( &peer_cert, session->security_parameters.cert_type, + &info->raw_certificate_list[0], CERT_NO_COPY)) < 0) { + gnutls_assert(); + return 0; } if (peer_cert.subject_pk_algorithm != GNUTLS_PK_RSA) { gnutls_assert(); - _gnutls_free_cert( &peer_cert); + _gnutls_cert_deinit( &peer_cert); return 0; } if ( _gnutls_mpi_get_nbits( peer_cert.params[0]) <= 512) { - _gnutls_free_cert( &peer_cert); + _gnutls_cert_deinit( &peer_cert); return 1; } - _gnutls_free_cert( &peer_cert); + _gnutls_cert_deinit( &peer_cert); return 0; } @@ -308,32 +284,11 @@ static int proc_rsa_export_server_kx(gnutls_session session, opaque * data, signature.data = &data[vparams.size + 2]; signature.size = sigsize; - switch( session->security_parameters.cert_type) { - case GNUTLS_CRT_X509: - if ((ret = - _gnutls_x509_cert2gnutls_cert( &peer_cert, - &info->raw_certificate_list[0], CERT_NO_COPY)) < 0) { - gnutls_assert(); - return ret; - } - break; - - case GNUTLS_CRT_OPENPGP: - if (_E_gnutls_openpgp_cert2gnutls_cert==NULL) { - gnutls_assert(); - return GNUTLS_E_INIT_LIBEXTRA; - } - if ((ret = - _E_gnutls_openpgp_cert2gnutls_cert( &peer_cert, - &info->raw_certificate_list[0])) < 0) { - gnutls_assert(); - return ret; - } - break; - - default: - gnutls_assert(); - return GNUTLS_E_INTERNAL_ERROR; + if ((ret = + _gnutls_cert2gnutls_cert( &peer_cert, session->security_parameters.cert_type, + &info->raw_certificate_list[0], CERT_NO_COPY)) < 0) { + gnutls_assert(); + return ret; } ret = @@ -341,7 +296,7 @@ static int proc_rsa_export_server_kx(gnutls_session session, opaque * data, &peer_cert, &vparams, &signature); - _gnutls_free_cert( &peer_cert); + _gnutls_cert_deinit( &peer_cert); if (ret < 0) { gnutls_assert(); } diff --git a/lib/gnutls_cert.c b/lib/gnutls_cert.c index e9ff2a8df6..26d2ad3ae6 100644 --- a/lib/gnutls_cert.c +++ b/lib/gnutls_cert.c @@ -59,7 +59,7 @@ void gnutls_certificate_free_keys(gnutls_certificate_credentials sc) for (i = 0; i < sc->ncerts; i++) { for (j = 0; j < sc->cert_list_length[i]; j++) { - _gnutls_free_cert( &sc->cert_list[i][j]); + _gnutls_cert_deinit( &sc->cert_list[i][j]); } gnutls_free( sc->cert_list[i]); } @@ -255,7 +255,7 @@ void gnutls_certificate_server_set_request(gnutls_session session, * the raw certificates (DER for X.509 or binary for OpenPGP), of the * client. * - * @req_ca_cert, is only used in X.509 certificates. + * @req_ca_dn, is only used in X.509 certificates. * Contains a list with the CA names that the server considers trusted. * Normally we should send a certificate that is signed * by one of these CAs. These names are DER encoded. To get a more @@ -317,6 +317,75 @@ void gnutls_certificate_server_set_select_function(gnutls_session session, session->internals.server_cert_callback = func; } +/** + * gnutls_certificate_client_set_retrieve_function - Used to set a callback to retrieve the certificate + * @session: is a &gnutls_session structure. + * @func: is the callback function + * + * This function sets a callback to be called in order to retrieve the certificate + * to be used in the handshake. + * The callback's function prototype is: + * int (*callback)(gnutls_session, const gnutls_datum* req_ca_dn, int nreqs, + * gnutls_datum **cert, unsigned int *ncerts, gnutls_key* key); + * + * @cert should contain @ncerts gnutls_datum structures which hold + * the raw certificates (DER for X.509 or binary for OpenPGP), of the + * client. Those should be allocated with gnutls_malloc(). The certificate + * type to be sent should be obtained using gnutls_certificate_type_get(); + * + * @key should contain a private key. + * + * @req_ca_cert, is only used in X.509 certificates. + * Contains a list with the CA names that the server considers trusted. + * Normally we should send a certificate that is signed + * by one of these CAs. These names are DER encoded. To get a more + * meaningful value use the function gnutls_x509_rdn_get(). + * + * If the callback function is provided then gnutls will call it, in the + * handshake, after the certificate request message has been received. + * + * The callback function should set the certificate list to be sent, and + * return 0 on success. The value (-1) indicates error and the handshake + * will be terminated. + **/ +void gnutls_certificate_client_set_retrieve_function(gnutls_session session, + gnutls_certificate_client_retrieve_function * func) +{ + session->internals.client_get_cert_callback = func; +} + +/** + * gnutls_certificate_server_set_retrieve_function - Used to set a callback to retrieve the certificate + * @session: is a &gnutls_session structure. + * @func: is the callback function + * + * This function sets a callback to be called in order to retrieve the certificate + * to be used in the handshake. + * The callback's function prototype is: + * int (*callback)(gnutls_session, gnutls_datum **cert, unsigned int *ncerts + * gnutls_key* key); + * + * @cert should contain @ncerts gnutls_datum structures which hold + * the raw certificates (DER for X.509 or binary for OpenPGP), of the + * server. Those should be allocated with gnutls_malloc(). The certificate + * type to be sent should be obtained using gnutls_certificate_type_get(); + * + * @key should contain a private key. + * + * If the callback function is provided then gnutls will call it, in the + * handshake, after the certificate request message has been received. + * + * The callback function should set the certificate list to be sent, and + * return 0 on success. The value (-1) indicates error and the handshake + * will be terminated. + **/ +void gnutls_certificate_server_set_retrieve_function(gnutls_session session, + gnutls_certificate_server_retrieve_function * func) +{ + session->internals.server_get_cert_callback = func; +} + + /* These are set by the gnutls_extra library's initialization function. */ @@ -499,6 +568,51 @@ time_t gnutls_certificate_activation_time_peers(gnutls_session session) } } +/* in auth_dhe.c */ +OPENPGP_CERT2GNUTLS_CERT _E_gnutls_openpgp_cert2gnutls_cert; +OPENPGP_KEY2GNUTLS_KEY _E_gnutls_openpgp_key2gnutls_key; + +int _gnutls_cert2gnutls_cert(gnutls_cert * gcert, gnutls_certificate_type type, + const gnutls_datum *raw_cert, int flags /* OR of ConvFlags */) +{ + switch( type) { + case GNUTLS_CRT_X509: + return _gnutls_x509_cert2gnutls_cert( gcert, + raw_cert, flags); + case GNUTLS_CRT_OPENPGP: + if (_E_gnutls_openpgp_cert2gnutls_cert==NULL) { + gnutls_assert(); + return GNUTLS_E_INIT_LIBEXTRA; + } + return + _E_gnutls_openpgp_cert2gnutls_cert( gcert, + raw_cert); + default: + gnutls_assert(); + return GNUTLS_E_INTERNAL_ERROR; + } +} + +int _gnutls_key2gnutls_key(gnutls_privkey * key, gnutls_certificate_type type, + const gnutls_datum *raw_key, int key_enc /* DER or PEM */) +{ + switch( type) { + case GNUTLS_CRT_X509: + return _gnutls_x509_key2gnutls_key( key, + raw_key, key_enc); + case GNUTLS_CRT_OPENPGP: + if (_E_gnutls_openpgp_key2gnutls_key==NULL) { + gnutls_assert(); + return GNUTLS_E_INIT_LIBEXTRA; + } + return + _E_gnutls_openpgp_key2gnutls_key( key, raw_key); + default: + gnutls_assert(); + return GNUTLS_E_INTERNAL_ERROR; + } +} + /* This function will convert a der certificate to a format * (structure) that gnutls can understand and use. Actually the @@ -593,10 +707,12 @@ int _gnutls_x509_crt2gnutls_cert(gnutls_cert * gcert, gnutls_x509_crt cert, } -void _gnutls_free_cert(gnutls_cert *cert) +void _gnutls_cert_deinit(gnutls_cert *cert) { int i; + if (cert == NULL) return; + for (i = 0; i < cert->params_size; i++) { _gnutls_mpi_release( &cert->params[i]); } diff --git a/lib/gnutls_cert.h b/lib/gnutls_cert.h index 3de12ef484..7c36b31cc9 100644 --- a/lib/gnutls_cert.h +++ b/lib/gnutls_cert.h @@ -85,12 +85,16 @@ int _gnutls_x509_cert2gnutls_cert(gnutls_cert * gcert, const gnutls_datum *derCe int flags); int _gnutls_x509_crt2gnutls_cert(gnutls_cert * gcert, gnutls_x509_crt cert, unsigned int flags); -void _gnutls_free_cert(gnutls_cert* cert); int _gnutls_cert_get_dn(gnutls_cert * cert, gnutls_datum * odn); void _gnutls_privkey_deinit(gnutls_privkey *key); +void _gnutls_cert_deinit(gnutls_cert *cert); int _gnutls_selected_cert_supported_kx(struct gnutls_session_int* session, gnutls_kx_algorithm ** alg, int *alg_size); - +int _gnutls_cert2gnutls_cert(gnutls_cert * gcert, gnutls_certificate_type type, + const gnutls_datum *raw_cert, int flags /* OR of ConvFlags */); +int _gnutls_key2gnutls_key(gnutls_privkey * key, gnutls_certificate_type type, + const gnutls_datum *raw_key, int key_enc /* DER or PEM */); + #endif diff --git a/lib/gnutls_int.h b/lib/gnutls_int.h index d61b7d5d36..888fb17a3f 100644 --- a/lib/gnutls_int.h +++ b/lib/gnutls_int.h @@ -221,6 +221,7 @@ typedef void (*LOG_FUNC)( int, const char*); typedef ssize_t (*gnutls_pull_func)(gnutls_transport_ptr, void*, size_t); typedef ssize_t (*gnutls_push_func)(gnutls_transport_ptr, const void*, size_t); + /* Store & Retrieve functions defines: */ typedef int (*gnutls_db_store_func)(void*, gnutls_datum key, gnutls_datum data); @@ -419,6 +420,16 @@ typedef int certificate_server_select_func(struct gnutls_session_int*, typedef int srp_server_select_func(struct gnutls_session_int*, const char**, const char**, unsigned int); +/* authentication function definitions: + */ +typedef int gnutls_certificate_client_retrieve_function( + struct gnutls_session_int*, const gnutls_datum* req_ca_cert, int nreqs, + gnutls_datum** certs, unsigned int* ncerts, gnutls_datum* key); + +typedef int gnutls_certificate_server_retrieve_function( + struct gnutls_session_int*, gnutls_datum **server_certs, unsigned int* ncerts, + gnutls_datum* key); + typedef struct { opaque header[HANDSHAKE_HEADER_SIZE]; /* this holds the number of bytes in the handshake_header[] */ @@ -538,6 +549,9 @@ typedef struct { certificate_client_select_func* client_cert_callback; certificate_server_select_func* server_cert_callback; + gnutls_certificate_client_retrieve_function* client_get_cert_callback; + gnutls_certificate_server_retrieve_function* server_get_cert_callback; + /* Callback to select the proper password file */ srp_server_select_func* server_srp_callback; @@ -573,13 +587,15 @@ typedef struct { */ uint16 proposed_record_size; - /* holds the index of the selected certificate. - * -1 if none. + /* holds the the selected certificate and key. + * use _gnutls_selected_certs_deinit() and _gnutls_selected_certs_set() + * to change them. */ gnutls_cert* selected_cert_list; int selected_cert_list_length; gnutls_privkey* selected_key; - + int selected_need_free; + /* holds the extensions we sent to the peer * (in case of a client) */ diff --git a/lib/gnutls_state.c b/lib/gnutls_state.c index 310f159ccb..711a2fdd31 100644 --- a/lib/gnutls_state.c +++ b/lib/gnutls_state.c @@ -273,6 +273,7 @@ void _gnutls_deinit(gnutls_session session) _gnutls_buffer_clear( &session->internals.record_send_buffer); gnutls_credentials_clear( session); + _gnutls_selected_certs_deinit( session); if (session->connection_state.read_cipher_state != NULL) _gnutls_cipher_deinit(session->connection_state.read_cipher_state); diff --git a/lib/gnutls_ui.h b/lib/gnutls_ui.h index ef050f9aba..9700d1ff58 100644 --- a/lib/gnutls_ui.h +++ b/lib/gnutls_ui.h @@ -17,6 +17,14 @@ typedef int gnutls_certificate_client_select_function( typedef int gnutls_certificate_server_select_function( gnutls_session, const gnutls_datum *server_certs, int ncerts); +typedef int gnutls_certificate_client_retrieve_function( + gnutls_session, const gnutls_datum* req_ca_cert, int nreqs, + gnutls_datum** certs, unsigned int* ncerts, gnutls_datum* key); +typedef int gnutls_certificate_server_retrieve_function( + gnutls_session, gnutls_datum **server_certs, unsigned int* ncerts + gnutls_datum* key); + + /* Functions that allow AUTH_INFO structures handling */ @@ -39,6 +47,9 @@ int gnutls_rsa_export_get_modulus_bits(gnutls_session session); void gnutls_certificate_client_set_select_function( gnutls_session, gnutls_certificate_client_select_function *); void gnutls_certificate_server_set_select_function( gnutls_session, gnutls_certificate_server_select_function *); +void gnutls_certificate_client_set_retrieve_function( gnutls_session, gnutls_certificate_client_retrieve_function *); +void gnutls_certificate_server_set_retrieve_function( gnutls_session, gnutls_certificate_server_retrieve_function *); + void gnutls_certificate_server_set_request( gnutls_session, gnutls_certificate_request); /* X.509 certificate handling functions diff --git a/lib/gnutls_x509.c b/lib/gnutls_x509.c index 6ee494064b..eaca68d83e 100644 --- a/lib/gnutls_x509.c +++ b/lib/gnutls_x509.c @@ -550,12 +550,43 @@ int i, ret; void _gnutls_privkey_deinit(gnutls_privkey *key) { int i; + if (key == NULL) return; for (i = 0; i < key->params_size; i++) { _gnutls_mpi_release( &key->params[i]); } } +int _gnutls_x509_key2gnutls_key( gnutls_privkey* privkey, const gnutls_datum* raw_key, + gnutls_x509_crt_fmt type) +{ +gnutls_x509_privkey tmpkey; +int ret; + + ret = gnutls_x509_privkey_init( &tmpkey); + if (ret < 0) { + gnutls_assert(); + return ret; + } + + ret = gnutls_x509_privkey_import( tmpkey, raw_key, type); + if (ret < 0) { + gnutls_assert(); + gnutls_x509_privkey_deinit( tmpkey); + return ret; + } + + ret = privkey_cpy( privkey, tmpkey); + if (ret < 0) { + gnutls_assert(); + gnutls_x509_privkey_deinit( tmpkey); + return ret; + } + + gnutls_x509_privkey_deinit( tmpkey); + + return 0; +} /* Reads a PEM encoded PKCS-1 RSA private key from memory * 2002-01-26: Added ability to read DSA keys. @@ -566,7 +597,6 @@ static int read_key_mem(gnutls_certificate_credentials res, const void *key, int { int ret; gnutls_datum tmp; - gnutls_x509_privkey tmpkey; /* allocate space for the pkey list */ @@ -576,33 +606,15 @@ static int read_key_mem(gnutls_certificate_credentials res, const void *key, int return GNUTLS_E_MEMORY_ERROR; } - ret = gnutls_x509_privkey_init( &tmpkey); //res->pkey[res->ncerts]); - if (ret < 0) { - gnutls_assert(); - return ret; - } - tmp.data = (opaque*)key; tmp.size = key_size; - ret = gnutls_x509_privkey_import( tmpkey, &tmp, type); - if (ret < 0) { - gnutls_assert(); - gnutls_x509_privkey_deinit( tmpkey); - - return ret; - } - - ret = privkey_cpy( &res->pkey[res->ncerts], tmpkey); + ret = _gnutls_x509_key2gnutls_key( &res->pkey[res->ncerts], &tmp, type); if (ret < 0) { gnutls_assert(); - gnutls_x509_privkey_deinit( tmpkey); - return ret; } - gnutls_x509_privkey_deinit( tmpkey); - return 0; } diff --git a/lib/gnutls_x509.h b/lib/gnutls_x509.h index b48c2e1038..81379dbe19 100644 --- a/lib/gnutls_x509.h +++ b/lib/gnutls_x509.h @@ -16,3 +16,5 @@ int _gnutls_check_key_usage( const gnutls_cert* cert, gnutls_kx_algorithm alg); int _gnutls_x509_read_rsa_params(opaque * der, int dersize, GNUTLS_MPI * params); int _gnutls_x509_read_dsa_pubkey(opaque * der, int dersize, GNUTLS_MPI * params); +int _gnutls_x509_key2gnutls_key( gnutls_privkey* privkey, const gnutls_datum* raw_key, + gnutls_x509_crt_fmt type); diff --git a/libextra/auth_srp_rsa.c b/libextra/auth_srp_rsa.c index 996d9f701f..725d7f5bc9 100644 --- a/libextra/auth_srp_rsa.c +++ b/libextra/auth_srp_rsa.c @@ -203,7 +203,7 @@ opaque* p; &peer_cert, &vparams, &signature); - _gnutls_free_cert( &peer_cert); + _gnutls_cert_deinit( &peer_cert); if (ret < 0) { gnutls_assert(); return ret; diff --git a/libextra/gnutls_extra.c b/libextra/gnutls_extra.c index 30e52c0187..8044b5d7b0 100644 --- a/libextra/gnutls_extra.c +++ b/libextra/gnutls_extra.c @@ -153,6 +153,7 @@ extern OPENPGP_KEY_CREATION_TIME_FUNC _E_gnutls_openpgp_extract_key_creation_tim extern OPENPGP_KEY_EXPIRATION_TIME_FUNC _E_gnutls_openpgp_extract_key_expiration_time; extern OPENPGP_VERIFY_KEY_FUNC _E_gnutls_openpgp_verify_key; extern OPENPGP_CERT2GNUTLS_CERT _E_gnutls_openpgp_cert2gnutls_cert; +extern OPENPGP_KEY2GNUTLS_KEY _E_gnutls_openpgp_key2gnutls_key; extern OPENPGP_FINGERPRINT _E_gnutls_openpgp_fingerprint; extern OPENPGP_KEY_REQUEST _E_gnutls_openpgp_request_key; @@ -164,6 +165,7 @@ static void _gnutls_add_openpgp_functions(void) { _E_gnutls_openpgp_fingerprint = gnutls_openpgp_fingerprint; _E_gnutls_openpgp_request_key = _gnutls_openpgp_request_key; _E_gnutls_openpgp_cert2gnutls_cert = _gnutls_openpgp_cert2gnutls_cert; + _E_gnutls_openpgp_key2gnutls_key = _gnutls_openpgp_key2gnutls_key; #endif } diff --git a/libextra/gnutls_extra.h b/libextra/gnutls_extra.h index a458512b9d..5da0886bc2 100644 --- a/libextra/gnutls_extra.h +++ b/libextra/gnutls_extra.h @@ -8,3 +8,4 @@ typedef int (*OPENPGP_KEY_REQUEST)(gnutls_session, gnutls_datum*, const gnutls_certificate_credentials, opaque*,int); typedef int (*OPENPGP_FINGERPRINT)(const gnutls_datum*, unsigned char*, size_t*); typedef int (*OPENPGP_CERT2GNUTLS_CERT)(gnutls_cert*, const gnutls_datum*); +typedef int (*OPENPGP_KEY2GNUTLS_KEY)(gnutls_privkey*, const gnutls_datum*); diff --git a/libextra/gnutls_openpgp.c b/libextra/gnutls_openpgp.c index b307e42783..97fc9ac3bd 100644 --- a/libextra/gnutls_openpgp.c +++ b/libextra/gnutls_openpgp.c @@ -292,7 +292,7 @@ openpgp_pk_to_gnutls_cert( gnutls_cert *cert, cdk_pkt_pubkey_t pk ) -*/ int _gnutls_openpgp_key2gnutls_key( gnutls_privkey *pkey, - gnutls_datum *raw_key ) + const gnutls_datum *raw_key ) { cdk_kbnode_t snode; CDK_PACKET *pkt; diff --git a/libextra/openpgp/gnutls_openpgp.h b/libextra/openpgp/gnutls_openpgp.h index 23a974b328..eabb52e97c 100644 --- a/libextra/openpgp/gnutls_openpgp.h +++ b/libextra/openpgp/gnutls_openpgp.h @@ -72,6 +72,10 @@ int _gnutls_openpgp_cert2gnutls_cert( gnutls_cert *cert, const gnutls_datum *raw ); +int +_gnutls_openpgp_key2gnutls_key( gnutls_privkey *pkey, + const gnutls_datum *raw_key); + int _gnutls_openpgp_request_key( gnutls_session, @@ -93,6 +97,9 @@ int gnutls_openpgp_fingerprint(const gnutls_datum * cert, time_t gnutls_openpgp_extract_key_creation_time(const gnutls_datum * cert); time_t gnutls_openpgp_extract_key_expiration_time(const gnutls_datum * cert); +int +_gnutls_openpgp_key2gnutls_key( gnutls_privkey *pkey, + const gnutls_datum *raw_key); #endif /*GNUTLS_OPENPGP_H*/