/** * gnutls_certificate_verify_peers2: * @session: is a gnutls session * @status: is the output of the verification * * This function will try to verify the peer's certificate and return * its status (trusted, invalid etc.). The value of @status should * be one or more of the gnutls_certificate_status_t enumerated * elements bitwise or'd. To avoid denial of service attacks some * default upper limits regarding the certificate key size and chain * size are set. To override them use * gnutls_certificate_set_verify_limits(). * * Note that you must also check the peer's name in order to check if * the verified certificate belongs to the actual peer, see gnutls_x509_crt_check_hostname(). * * Returns: a negative error code on error and %GNUTLS_E_SUCCESS (0) on success. **/ int gnutls_certificate_verify_peers2 (gnutls_session_t session, unsigned int *status) { cert_auth_info_t info; CHECK_AUTH (GNUTLS_CRD_CERTIFICATE, GNUTLS_E_INVALID_REQUEST); info = _gnutls_get_auth_info (session); if (info == NULL) { return GNUTLS_E_NO_CERTIFICATE_FOUND; } if (info->raw_certificate_list == NULL || info->ncerts == 0) return GNUTLS_E_NO_CERTIFICATE_FOUND; switch (gnutls_certificate_type_get (session)) { case GNUTLS_CRT_X509: return _gnutls_x509_cert_verify_peers (session, status); #ifdef ENABLE_OPENPGP case GNUTLS_CRT_OPENPGP: return _gnutls_openpgp_crt_verify_peers (session, status); #endif default: return GNUTLS_E_INVALID_REQUEST; } }
/** * gnutls_certificate_expiration_time_peers: * @session: is a gnutls session * * This function will return the peer's certificate expiration time. * * Returns: (time_t)-1 on error. * * Deprecated: gnutls_certificate_verify_peers2() now verifies expiration times. **/ time_t gnutls_certificate_expiration_time_peers (gnutls_session_t session) { cert_auth_info_t info; CHECK_AUTH (GNUTLS_CRD_CERTIFICATE, GNUTLS_E_INVALID_REQUEST); info = _gnutls_get_auth_info (session); if (info == NULL) { return (time_t) - 1; } if (info->raw_certificate_list == NULL || info->ncerts == 0) { gnutls_assert (); return (time_t) - 1; } switch (gnutls_certificate_type_get (session)) { case GNUTLS_CRT_X509: return _gnutls_x509_get_raw_crt_expiration_time (&info->raw_certificate_list [0]); #ifdef ENABLE_OPENPGP case GNUTLS_CRT_OPENPGP: return _gnutls_openpgp_get_raw_key_expiration_time (&info->raw_certificate_list[0]); #endif default: return (time_t) - 1; } }
/* just read the username from the client key exchange. */ int _gnutls_proc_psk_client_kx (gnutls_session_t session, opaque * data, size_t _data_size) { ssize_t data_size = _data_size; int ret; gnutls_datum_t username; gnutls_psk_server_credentials_t cred; psk_auth_info_t info; cred = (gnutls_psk_server_credentials_t) _gnutls_get_cred (session->key, GNUTLS_CRD_PSK, NULL); if (cred == NULL) { gnutls_assert (); return GNUTLS_E_INSUFFICIENT_CREDENTIALS; } if ((ret = _gnutls_auth_info_set (session, GNUTLS_CRD_PSK, sizeof (psk_auth_info_st), 1)) < 0) { gnutls_assert (); return ret; } DECR_LEN (data_size, 2); username.size = _gnutls_read_uint16 (&data[0]); DECR_LEN (data_size, username.size); username.data = &data[2]; /* copy the username to the auth info structures */ info = _gnutls_get_auth_info (session); if (username.size > MAX_USERNAME_SIZE) { gnutls_assert (); return GNUTLS_E_ILLEGAL_SRP_USERNAME; } memcpy (info->username, username.data, username.size); info->username[username.size] = 0; ret = _gnutls_set_psk_session_key (session, NULL); if (ret < 0) { gnutls_assert (); goto error; } ret = 0; error: return ret; }
/* Generates the PSK client key exchange * * * struct { * select (KeyExchangeAlgorithm) { * uint8_t psk_identity<0..2^16-1>; * } exchange_keys; * } ClientKeyExchange; * */ int _gnutls_gen_psk_client_kx(gnutls_session_t session, gnutls_buffer_st * data) { int ret, free; gnutls_datum_t username = {NULL, 0}; gnutls_datum_t key; gnutls_psk_client_credentials_t cred; psk_auth_info_t info; cred = (gnutls_psk_client_credentials_t) _gnutls_get_cred(session, GNUTLS_CRD_PSK); if (cred == NULL) { gnutls_assert(); return GNUTLS_E_INSUFFICIENT_CREDENTIALS; } info = _gnutls_get_auth_info(session, GNUTLS_CRD_PSK); if (info == NULL) { gnutls_assert(); return GNUTLS_E_INTERNAL_ERROR; } ret = _gnutls_find_psk_key(session, cred, &username, &key, &free); if (ret < 0) return gnutls_assert_val(ret); ret = _gnutls_set_psk_session_key(session, &key, NULL); if (ret < 0) { gnutls_assert(); goto cleanup; } ret = _gnutls_buffer_append_data_prefix(data, 16, username.data, username.size); if (ret < 0) { gnutls_assert(); } if (username.size > sizeof(info->username)-1) { gnutls_assert(); ret = GNUTLS_E_ILLEGAL_SRP_USERNAME; goto cleanup; } assert(username.data != NULL); memcpy(info->username, username.data, username.size); info->username[username.size] = 0; cleanup: if (free) { gnutls_free(username.data); _gnutls_free_temp_key_datum(&key); } return ret; }
/** * gnutls_dh_get_prime_bits: * @session: is a gnutls session * * This function will return the bits of the prime used in the last * Diffie-Hellman key exchange with the peer. Should be used for both * anonymous and ephemeral Diffie-Hellman. Note that some ciphers, * like RSA and DSA without DHE, do not use a Diffie-Hellman key * exchange, and then this function will return 0. * * Returns: The Diffie-Hellman bit strength is returned, or 0 if no * Diffie-Hellman key exchange was done, or a negative error code on * failure. **/ int gnutls_dh_get_prime_bits(gnutls_session_t session) { dh_info_st *dh; switch (gnutls_auth_get_type(session)) { case GNUTLS_CRD_ANON: { anon_auth_info_t info; info = _gnutls_get_auth_info(session, GNUTLS_CRD_ANON); if (info == NULL) return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); dh = &info->dh; break; } case GNUTLS_CRD_PSK: { psk_auth_info_t info; info = _gnutls_get_auth_info(session, GNUTLS_CRD_PSK); if (info == NULL) return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); dh = &info->dh; break; } case GNUTLS_CRD_CERTIFICATE: { cert_auth_info_t info; info = _gnutls_get_auth_info(session, GNUTLS_CRD_CERTIFICATE); if (info == NULL) return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); dh = &info->dh; break; } default: gnutls_assert(); return GNUTLS_E_INVALID_REQUEST; } if(dh->prime.size == 0) return 0; return mpi_buf2bits(&dh->prime); }
/*- * _gnutls_openpgp_crt_verify_peers - This function returns the peer's certificate status * @session: is a gnutls session * * This function will try to verify the peer's certificate and return its status (TRUSTED, INVALID etc.). * Returns a negative error code in case of an error, or GNUTLS_E_NO_CERTIFICATE_FOUND if no certificate was sent. * -*/ int _gnutls_openpgp_crt_verify_peers (gnutls_session_t session, unsigned int *status) { cert_auth_info_t info; gnutls_certificate_credentials_t cred; int peer_certificate_list_size, ret; CHECK_AUTH (GNUTLS_CRD_CERTIFICATE, GNUTLS_E_INVALID_REQUEST); info = _gnutls_get_auth_info (session); if (info == NULL) return GNUTLS_E_INVALID_REQUEST; cred = (gnutls_certificate_credentials_t) _gnutls_get_cred (session->key, GNUTLS_CRD_CERTIFICATE, NULL); if (cred == NULL) { gnutls_assert (); return GNUTLS_E_INSUFFICIENT_CREDENTIALS; } if (info->raw_certificate_list == NULL || info->ncerts == 0) { gnutls_assert (); return GNUTLS_E_NO_CERTIFICATE_FOUND; } /* generate a list of gnutls_certs based on the auth info * raw certs. */ peer_certificate_list_size = info->ncerts; if (peer_certificate_list_size != 1) { gnutls_assert (); return GNUTLS_E_INTERNAL_ERROR; } /* Verify certificate */ if (_E_gnutls_openpgp_verify_key == NULL) { gnutls_assert (); return GNUTLS_E_INIT_LIBEXTRA; } ret = _E_gnutls_openpgp_verify_key (cred, &info->raw_certificate_list[0], peer_certificate_list_size, status); if (ret < 0) { gnutls_assert (); return ret; } return 0; }
static int unpack_psk_auth_info (gnutls_session_t session, gnutls_buffer_st * ps) { size_t username_size, hint_size; int ret; psk_auth_info_t info; ret = _gnutls_auth_info_set (session, GNUTLS_CRD_PSK, sizeof (psk_auth_info_st), 1); if (ret < 0) { gnutls_assert (); return ret; } info = _gnutls_get_auth_info (session); if (info == NULL) { gnutls_assert (); return GNUTLS_E_INTERNAL_ERROR; } BUFFER_POP_NUM (ps, username_size); if (username_size > sizeof (info->username)) { gnutls_assert (); return GNUTLS_E_INTERNAL_ERROR; } BUFFER_POP (ps, info->username, username_size); BUFFER_POP_NUM (ps, hint_size); if (hint_size > sizeof (info->hint)) { gnutls_assert (); return GNUTLS_E_INTERNAL_ERROR; } BUFFER_POP (ps, info->hint, hint_size); BUFFER_POP_NUM (ps, info->dh.secret_bits); BUFFER_POP_DATUM (ps, &info->dh.prime); BUFFER_POP_DATUM (ps, &info->dh.generator); BUFFER_POP_DATUM (ps, &info->dh.public_key); ret = 0; error: _gnutls_free_datum (&info->dh.prime); _gnutls_free_datum (&info->dh.generator); _gnutls_free_datum (&info->dh.public_key); return ret; }
/** * gnutls_dh_get_pubkey: * @session: is a gnutls session * @raw_key: will hold the public key. * * This function will return the peer's public key used in the last * Diffie-Hellman key exchange. This function should be used for both * anonymous and ephemeral Diffie-Hellman. The output parameters must * be freed with gnutls_free(). * * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise * an error code is returned. **/ int gnutls_dh_get_pubkey(gnutls_session_t session, gnutls_datum_t * raw_key) { dh_info_st *dh; anon_auth_info_t anon_info; cert_auth_info_t cert_info; cert_auth_info_t psk_info; switch (gnutls_auth_get_type(session)) { case GNUTLS_CRD_ANON: { anon_info = _gnutls_get_auth_info(session, GNUTLS_CRD_ANON); if (anon_info == NULL) return GNUTLS_E_INTERNAL_ERROR; dh = &anon_info->dh; break; } case GNUTLS_CRD_PSK: { psk_info = _gnutls_get_auth_info(session, GNUTLS_CRD_PSK); if (psk_info == NULL) return GNUTLS_E_INTERNAL_ERROR; dh = &psk_info->dh; break; } case GNUTLS_CRD_CERTIFICATE: { cert_info = _gnutls_get_auth_info(session, GNUTLS_CRD_CERTIFICATE); if (cert_info == NULL) return GNUTLS_E_INTERNAL_ERROR; dh = &cert_info->dh; break; } default: gnutls_assert(); return GNUTLS_E_INVALID_REQUEST; } return _gnutls_set_datum(raw_key, dh->public_key.data, dh->public_key.size); }
/** * gnutls_srp_server_get_username: * @session: is a gnutls session * * This function will return the username of the peer. This should * only be called in case of SRP authentication and in case of a * server. Returns NULL in case of an error. * * Returns: SRP username of the peer, or NULL in case of error. **/ const char *gnutls_srp_server_get_username(gnutls_session_t session) { srp_server_auth_info_t info; CHECK_AUTH(GNUTLS_CRD_SRP, NULL); info = _gnutls_get_auth_info(session, GNUTLS_CRD_SRP); if (info == NULL) return NULL; return info->username; }
/* just read the hint from the server key exchange. */ static int _gnutls_proc_psk_server_kx(gnutls_session_t session, uint8_t * data, size_t _data_size) { ssize_t data_size = _data_size; int ret; gnutls_datum_t hint; gnutls_psk_client_credentials_t cred; psk_auth_info_t info; cred = (gnutls_psk_client_credentials_t) _gnutls_get_cred(session, GNUTLS_CRD_PSK); if (cred == NULL) { gnutls_assert(); return GNUTLS_E_INSUFFICIENT_CREDENTIALS; } if ((ret = _gnutls_auth_info_set(session, GNUTLS_CRD_PSK, sizeof(psk_auth_info_st), 1)) < 0) { gnutls_assert(); return ret; } DECR_LENGTH_RET(data_size, 2, 0); hint.size = _gnutls_read_uint16(&data[0]); DECR_LEN(data_size, hint.size); hint.data = &data[2]; /* copy the hint to the auth info structures */ info = _gnutls_get_auth_info(session, GNUTLS_CRD_PSK); if (info == NULL) { gnutls_assert(); return GNUTLS_E_INTERNAL_ERROR; } if (hint.size > sizeof(info->hint)-1) { gnutls_assert(); return GNUTLS_E_ILLEGAL_SRP_USERNAME; } memcpy(info->hint, hint.data, hint.size); info->hint[hint.size] = 0; ret = 0; return ret; }
/* Format: * 1 byte the credentials type * 4 bytes the size of the whole structure * 2 bytes the size of secret key in bits * 4 bytes the size of the prime * x bytes the prime * 4 bytes the size of the generator * x bytes the generator * 4 bytes the size of the public key * x bytes the public key */ static int pack_anon_auth_info (gnutls_session_t session, gnutls_datum_t * packed_session) { anon_auth_info_t info = _gnutls_get_auth_info (session); int pos = 0; size_t pack_size; if (info == NULL && session->key->auth_info_size != 0) { gnutls_assert (); return GNUTLS_E_INVALID_REQUEST; } if (info) pack_size = 2 + 4 * 3 + info->dh.prime.size + info->dh.generator.size + info->dh.public_key.size; else pack_size = 0; packed_session->size = PACK_HEADER_SIZE + pack_size + sizeof (uint32_t); /* calculate the size and allocate the data. */ packed_session->data = gnutls_malloc (packed_session->size + MAX_SEC_PARAMS); if (packed_session->data == NULL) { gnutls_assert (); return GNUTLS_E_MEMORY_ERROR; } packed_session->data[0] = GNUTLS_CRD_ANON; _gnutls_write_uint32 (pack_size, &packed_session->data[PACK_HEADER_SIZE]); pos += 4 + PACK_HEADER_SIZE; if (pack_size > 0) { _gnutls_write_uint16 (info->dh.secret_bits, &packed_session->data[pos]); pos += 2; _gnutls_write_datum32 (&packed_session->data[pos], info->dh.prime); pos += 4 + info->dh.prime.size; _gnutls_write_datum32 (&packed_session->data[pos], info->dh.generator); pos += 4 + info->dh.generator.size; _gnutls_write_datum32 (&packed_session->data[pos], info->dh.public_key); pos += 4 + info->dh.public_key.size; } return 0; }
/* This function reads the RSA parameters from peer's certificate; */ int _gnutls_get_public_rsa_params(gnutls_session_t session, gnutls_pk_params_st * params) { int ret; cert_auth_info_t info; unsigned key_usage; gnutls_pcert_st peer_cert; /* normal non export case */ info = _gnutls_get_auth_info(session, GNUTLS_CRD_CERTIFICATE); if (info == NULL || info->ncerts == 0) { gnutls_assert(); return GNUTLS_E_INTERNAL_ERROR; } ret = _gnutls_get_auth_info_pcert(&peer_cert, session->security_parameters. cert_type, info); if (ret < 0) { gnutls_assert(); return ret; } gnutls_pubkey_get_key_usage(peer_cert.pubkey, &key_usage); ret = check_key_usage_for_enc(session, key_usage); if (ret < 0) { gnutls_assert(); goto cleanup2; } gnutls_pk_params_init(params); ret = _gnutls_pubkey_get_mpis(peer_cert.pubkey, params); if (ret < 0) { ret = gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); goto cleanup2; } gnutls_pcert_deinit(&peer_cert); return 0; cleanup2: gnutls_pcert_deinit(&peer_cert); return ret; }
static int unpack_srp_auth_info (gnutls_session_t session, const gnutls_datum_t * packed_session) { size_t username_size; int ret; srp_server_auth_info_t info; if (packed_session->data[0] != GNUTLS_CRD_SRP) { gnutls_assert (); return GNUTLS_E_INVALID_REQUEST; } username_size = _gnutls_read_uint32 (&packed_session->data[PACK_HEADER_SIZE]); if (username_size == 0) return 0; /* nothing to be done */ /* a simple check for integrity */ if (username_size + 4 + PACK_HEADER_SIZE > packed_session->size) { gnutls_assert (); return GNUTLS_E_INVALID_REQUEST; } ret = _gnutls_auth_info_set (session, GNUTLS_CRD_SRP, sizeof (srp_server_auth_info_st), 1); if (ret < 0) { gnutls_assert (); return ret; } info = _gnutls_get_auth_info (session); if (info == NULL) { gnutls_assert (); return GNUTLS_E_INTERNAL_ERROR; } memcpy (info->username, &packed_session->data[PACK_HEADER_SIZE + sizeof (uint32_t)], username_size); return 0; }
/** * gnutls_dh_get_secret_bits: * @session: is a gnutls session * * This function will return the bits used in the last Diffie-Hellman * key exchange with the peer. Should be used for both anonymous and * ephemeral Diffie-Hellman. * * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise * an error code is returned. **/ int gnutls_dh_get_secret_bits(gnutls_session_t session) { switch (gnutls_auth_get_type(session)) { case GNUTLS_CRD_ANON: { anon_auth_info_t info; info = _gnutls_get_auth_info(session, GNUTLS_CRD_ANON); if (info == NULL) return GNUTLS_E_INTERNAL_ERROR; return info->dh.secret_bits; } case GNUTLS_CRD_PSK: { psk_auth_info_t info; info = _gnutls_get_auth_info(session, GNUTLS_CRD_PSK); if (info == NULL) return GNUTLS_E_INTERNAL_ERROR; return info->dh.secret_bits; } case GNUTLS_CRD_CERTIFICATE: { cert_auth_info_t info; info = _gnutls_get_auth_info(session, GNUTLS_CRD_CERTIFICATE); if (info == NULL) return GNUTLS_E_INTERNAL_ERROR; return info->dh.secret_bits; } default: gnutls_assert(); return GNUTLS_E_INVALID_REQUEST; } }
/** * gnutls_certificate_get_peers: * @session: is a gnutls session * @list_size: is the length of the certificate list * * Get the peer's raw certificate (chain) as sent by the peer. These * certificates are in raw format (DER encoded for X.509). In case of * a X.509 then a certificate list may be present. The first * certificate in the list is the peer's certificate, following the * issuer's certificate, then the issuer's issuer etc. * * In case of OpenPGP keys a single key will be returned in raw * format. * * Returns: a pointer to a #gnutls_datum_t containing our * certificates, or %NULL in case of an error or if no certificate * was used. **/ const gnutls_datum_t *gnutls_certificate_get_peers(gnutls_session_t session, unsigned int *list_size) { cert_auth_info_t info; CHECK_AUTH(GNUTLS_CRD_CERTIFICATE, NULL); info = _gnutls_get_auth_info(session, GNUTLS_CRD_CERTIFICATE); if (info == NULL) return NULL; *list_size = info->ncerts; return info->raw_certificate_list; }
static int unpack_anon_auth_info (gnutls_session_t session, gnutls_buffer_st * ps) { int ret; size_t pack_size; anon_auth_info_t info = NULL; BUFFER_POP_NUM (ps, pack_size); if (pack_size == 0) return 0; /* nothing to be done */ /* client and server have the same auth_info here */ ret = _gnutls_auth_info_set (session, GNUTLS_CRD_ANON, sizeof (anon_auth_info_st), 1); if (ret < 0) { gnutls_assert (); return ret; } info = _gnutls_get_auth_info (session); if (info == NULL) { gnutls_assert (); return GNUTLS_E_INTERNAL_ERROR; } BUFFER_POP_NUM (ps, info->dh.secret_bits); BUFFER_POP_DATUM (ps, &info->dh.prime); BUFFER_POP_DATUM (ps, &info->dh.generator); BUFFER_POP_DATUM (ps, &info->dh.public_key); return 0; error: if (info) { _gnutls_free_datum (&info->dh.prime); _gnutls_free_datum (&info->dh.generator); _gnutls_free_datum (&info->dh.public_key); } return ret; }
/** * gnutls_psk_server_get_username - return the username of the peer * @session: is a gnutls session * * This should only be called in case of PSK authentication and in * case of a server. * * Returns: the username of the peer, or %NULL in case of an error. **/ const char * gnutls_psk_server_get_username (gnutls_session_t session) { psk_auth_info_t info; CHECK_AUTH (GNUTLS_CRD_PSK, NULL); info = _gnutls_get_auth_info (session); if (info == NULL) return NULL; if (info->username[0] != 0) return info->username; return NULL; }
/** * gnutls_psk_client_get_hint - return the PSK identity hint of the peer * @session: is a gnutls session * * The PSK identity hint may give the client help in deciding which * username to use. This should only be called in case of PSK * authentication and in case of a client. * * Returns: the identity hint of the peer, or %NULL in case of an error. * * Since: 2.4.0 **/ const char * gnutls_psk_client_get_hint (gnutls_session_t session) { psk_auth_info_t info; CHECK_AUTH (GNUTLS_CRD_PSK, NULL); info = _gnutls_get_auth_info (session); if (info == NULL) return NULL; if (info->hint[0] != 0) return info->hint; return NULL; }
/** * gnutls_certificate_get_peers_subkey_id: * @session: is a gnutls session * @id: will contain the ID * * Get the peer's subkey ID when OpenPGP certificates are * used. The returned @id should be treated as constant. * * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise * an error code is returned. * * Since: 3.1.3 **/ int gnutls_certificate_get_peers_subkey_id(gnutls_session_t session, gnutls_datum_t * id) { cert_auth_info_t info; CHECK_AUTH(GNUTLS_CRD_CERTIFICATE, GNUTLS_E_INVALID_REQUEST); info = _gnutls_get_auth_info(session, GNUTLS_CRD_CERTIFICATE); if (info == NULL) return GNUTLS_E_INVALID_REQUEST; id->data = info->subkey_id; id->size = GNUTLS_OPENPGP_KEYID_SIZE; return 0; }
/* if the peer's certificate is of 512 bits or less, returns non zero. */ int _gnutls_peers_cert_less_512 (gnutls_session_t session) { gnutls_cert peer_cert; int ret; cert_auth_info_t info = _gnutls_get_auth_info (session); if (info == NULL || info->ncerts == 0) { gnutls_assert (); /* we need this in order to get peer's certificate */ return 0; } if ((ret = _gnutls_get_auth_info_gcert (&peer_cert, session->security_parameters.cert_type, info, CERT_NO_COPY)) < 0) { gnutls_assert (); return 0; } if (peer_cert.subject_pk_algorithm != GNUTLS_PK_RSA) { gnutls_assert (); _gnutls_gcert_deinit (&peer_cert); return 0; } if (_gnutls_mpi_get_nbits (peer_cert.params[0]) <= 512) { _gnutls_gcert_deinit (&peer_cert); return 1; } _gnutls_gcert_deinit (&peer_cert); return 0; }
/* if the peer's certificate is of 512 bits or less, returns non zero. */ int _gnutls_peers_cert_less_512 (gnutls_session_t session) { gnutls_pcert_st peer_cert; int ret; cert_auth_info_t info = _gnutls_get_auth_info (session); if (info == NULL || info->ncerts == 0) { gnutls_assert (); /* we need this in order to get peer's certificate */ return 0; } if ((ret = _gnutls_get_auth_info_pcert (&peer_cert, session->security_parameters.cert_type, info)) < 0) { gnutls_assert (); return 0; } if (gnutls_pubkey_get_pk_algorithm(peer_cert.pubkey, NULL) != GNUTLS_PK_RSA) { gnutls_assert (); gnutls_pcert_deinit (&peer_cert); return 0; } if (_gnutls_pubkey_is_over_rsa_512(peer_cert.pubkey) < 0) { gnutls_pcert_deinit (&peer_cert); return 1; } gnutls_pcert_deinit (&peer_cert); return 0; }
/* Format: * 1 byte the credentials type * 4 bytes the size of the SRP username (x) * x bytes the SRP username */ static int pack_srp_auth_info (gnutls_session_t session, gnutls_datum_t * packed_session) { srp_server_auth_info_t info = _gnutls_get_auth_info (session); int pack_size; if (info == NULL && session->key->auth_info_size != 0) { gnutls_assert (); return GNUTLS_E_INVALID_REQUEST; } if (info && info->username) pack_size = strlen (info->username) + 1; /* include the terminating null */ else pack_size = 0; packed_session->size = PACK_HEADER_SIZE + pack_size + sizeof (uint32_t); /* calculate the size and allocate the data. */ packed_session->data = gnutls_malloc (packed_session->size + MAX_SEC_PARAMS); if (packed_session->data == NULL) { gnutls_assert (); return GNUTLS_E_MEMORY_ERROR; } packed_session->data[0] = GNUTLS_CRD_SRP; _gnutls_write_uint32 (pack_size, &packed_session->data[PACK_HEADER_SIZE]); if (pack_size > 0) memcpy (&packed_session->data[PACK_HEADER_SIZE + sizeof (uint32_t)], info->username, pack_size + 1); return 0; }
/* Format: * 1 byte the credentials type * 4 bytes the size of the whole structure * * 4 bytes the size of the PSK username (x) * x bytes the PSK username * 2 bytes the size of secret key in bits * 4 bytes the size of the prime * x bytes the prime * 4 bytes the size of the generator * x bytes the generator * 4 bytes the size of the public key * x bytes the public key */ static int pack_psk_auth_info (gnutls_session_t session, gnutls_buffer_st * ps) { psk_auth_info_t info; int username_len; int hint_len, ret; int size_offset; size_t cur_size; info = _gnutls_get_auth_info (session); if (info && info->username) username_len = strlen (info->username) + 1; /* include the terminating null */ else username_len = 0; if (info && info->hint) hint_len = strlen (info->hint) + 1; /* include the terminating null */ else hint_len = 0; size_offset = ps->length; BUFFER_APPEND_NUM (ps, 0); cur_size = ps->length; BUFFER_APPEND_PFX (ps, info->username, username_len); BUFFER_APPEND_PFX (ps, info->hint, hint_len); BUFFER_APPEND_NUM (ps, info->dh.secret_bits); BUFFER_APPEND_PFX (ps, info->dh.prime.data, info->dh.prime.size); BUFFER_APPEND_PFX (ps, info->dh.generator.data, info->dh.generator.size); BUFFER_APPEND_PFX (ps, info->dh.public_key.data, info->dh.public_key.size); /* write the real size */ _gnutls_write_uint32 (ps->length - cur_size, ps->data + size_offset); return 0; }
/* Format: * 1 byte the credentials type * 4 bytes the size of the whole structure * DH stuff * 2 bytes the size of secret key in bits * 4 bytes the size of the prime * x bytes the prime * 4 bytes the size of the generator * x bytes the generator * 4 bytes the size of the public key * x bytes the public key * RSA stuff * 4 bytes the size of the modulus * x bytes the modulus * 4 bytes the size of the exponent * x bytes the exponent * CERTIFICATES * 4 bytes the length of the certificate list * 4 bytes the size of first certificate * x bytes the certificate * and so on... */ static int pack_certificate_auth_info (gnutls_session_t session, gnutls_buffer_st * ps) { unsigned int i; int cur_size, ret; cert_auth_info_t info = _gnutls_get_auth_info (session); int size_offset; size_offset = ps->length; BUFFER_APPEND_NUM (ps, 0); cur_size = ps->length; if (info) { BUFFER_APPEND_NUM (ps, info->dh.secret_bits); BUFFER_APPEND_PFX (ps, info->dh.prime.data, info->dh.prime.size); BUFFER_APPEND_PFX (ps, info->dh.generator.data, info->dh.generator.size); BUFFER_APPEND_PFX (ps, info->dh.public_key.data, info->dh.public_key.size); BUFFER_APPEND_PFX (ps, info->rsa_export.modulus.data, info->rsa_export.modulus.size); BUFFER_APPEND_PFX (ps, info->rsa_export.exponent.data, info->rsa_export.exponent.size); BUFFER_APPEND_NUM (ps, info->ncerts); for (i = 0; i < info->ncerts; i++) BUFFER_APPEND_PFX (ps, info->raw_certificate_list[i].data, info->raw_certificate_list[i].size); } /* write the real size */ _gnutls_write_uint32 (ps->length - cur_size, ps->data + size_offset); return 0; }
static int unpack_srp_auth_info (gnutls_session_t session, gnutls_buffer_st * ps) { size_t username_size; int ret; srp_server_auth_info_t info; BUFFER_POP_NUM (ps, username_size); if (username_size > sizeof (info->username)) { gnutls_assert (); return GNUTLS_E_INTERNAL_ERROR; } ret = _gnutls_auth_info_set (session, GNUTLS_CRD_SRP, sizeof (srp_server_auth_info_st), 1); if (ret < 0) { gnutls_assert (); return ret; } info = _gnutls_get_auth_info (session); if (info == NULL) { gnutls_assert (); return GNUTLS_E_INTERNAL_ERROR; } BUFFER_POP (ps, info->username, username_size); ret = 0; error: return ret; }
/* Format: * 1 byte the credentials type * 4 bytes the size of the SRP username (x) * x bytes the SRP username */ static int pack_srp_auth_info (gnutls_session_t session, gnutls_buffer_st * ps) { srp_server_auth_info_t info = _gnutls_get_auth_info (session); int len, ret; int size_offset; size_t cur_size; if (info && info->username) len = strlen (info->username) + 1; /* include the terminating null */ else len = 0; size_offset = ps->length; BUFFER_APPEND_NUM (ps, 0); cur_size = ps->length; BUFFER_APPEND_PFX (ps, info->username, len); /* write the real size */ _gnutls_write_uint32 (ps->length - cur_size, ps->data + size_offset); return 0; }
static int proc_dhe_server_kx (gnutls_session_t session, opaque * data, size_t _data_size) { int sigsize; opaque *sigdata; gnutls_datum_t vparams, signature; int ret; cert_auth_info_t info = _gnutls_get_auth_info (session); ssize_t data_size = _data_size; gnutls_cert peer_cert; gnutls_sign_algorithm_t sign_algo = GNUTLS_SIGN_UNKNOWN; gnutls_protocol_t ver = gnutls_protocol_get_version (session); if (info == NULL || info->ncerts == 0) { gnutls_assert (); /* we need this in order to get peer's certificate */ return GNUTLS_E_INTERNAL_ERROR; } ret = _gnutls_proc_dh_common_server_kx (session, data, _data_size, 0); if (ret < 0) { gnutls_assert (); return ret; } /* VERIFY SIGNATURE */ vparams.size = ret; vparams.data = data; sigdata = &data[vparams.size]; if (_gnutls_version_has_selectable_sighash (ver)) { sign_algorithm_st aid; DECR_LEN (data_size, 1); aid.hash_algorithm = *sigdata++; DECR_LEN (data_size, 1); aid.sign_algorithm = *sigdata++; sign_algo = _gnutls_tls_aid_to_sign (&aid); if (sign_algo == GNUTLS_SIGN_UNKNOWN) { gnutls_assert (); return GNUTLS_E_UNSUPPORTED_SIGNATURE_ALGORITHM; } } DECR_LEN (data_size, 2); sigsize = _gnutls_read_uint16 (sigdata); sigdata += 2; DECR_LEN (data_size, sigsize); signature.data = sigdata; signature.size = sigsize; if ((ret = _gnutls_get_auth_info_gcert (&peer_cert, session->security_parameters.cert_type, info, CERT_NO_COPY)) < 0) { gnutls_assert (); return ret; } ret = _gnutls_handshake_verify_data (session, &peer_cert, &vparams, &signature, sign_algo); _gnutls_gcert_deinit (&peer_cert); if (ret < 0) { gnutls_assert (); return ret; } return ret; }
static int proc_psk_client_kx (gnutls_session_t session, opaque * data, size_t _data_size) { int bits; int ret; mpi_t p, g; gnutls_dh_params_t dh_params; const mpi_t *mpis; gnutls_psk_server_credentials_t cred; psk_auth_info_t info; gnutls_datum_t username; ssize_t data_size = _data_size; cred = (gnutls_psk_server_credentials_t) _gnutls_get_cred (session->key, GNUTLS_CRD_PSK, NULL); if (cred == NULL) { gnutls_assert (); return GNUTLS_E_INSUFFICIENT_CREDENTIALS; } bits = _gnutls_dh_get_allowed_prime_bits (session); if ((ret = _gnutls_auth_info_set (session, GNUTLS_CRD_PSK, sizeof (psk_auth_info_st), 1)) < 0) { gnutls_assert (); return ret; } dh_params = _gnutls_get_dh_params (cred->dh_params, cred->params_func, session); mpis = _gnutls_dh_params_to_mpi (dh_params); if (mpis == NULL) { gnutls_assert (); return GNUTLS_E_NO_TEMPORARY_DH_PARAMS; } p = mpis[0]; g = mpis[1]; DECR_LEN (data_size, 2); username.size = _gnutls_read_uint16 (&data[0]); DECR_LEN (data_size, username.size); username.data = &data[2]; /* copy the username to the auth info structures */ info = _gnutls_get_auth_info (session); if (username.size > MAX_SRP_USERNAME) { gnutls_assert (); return GNUTLS_E_ILLEGAL_SRP_USERNAME; } memcpy (info->username, username.data, username.size); info->username[username.size] = 0; /* Adjust the data */ data += username.size + 2; ret = _gnutls_proc_dh_common_client_kx (session, data, data_size, g, p); return ret; }
/* Send the first key exchange message ( g, n, s) and append the verifier algorithm number * Data is allocated by the caller, and should have data_size size. */ int _gnutls_gen_srp_server_kx (gnutls_session_t session, opaque ** data) { int ret; uint8_t *data_n, *data_s; uint8_t *data_g; char *username; SRP_PWD_ENTRY *pwd_entry; srp_server_auth_info_t info; ssize_t data_size; size_t n_b, tmp_size; char buf[64]; uint8_t *data_b; if ((ret = _gnutls_auth_info_set (session, GNUTLS_CRD_SRP, sizeof (srp_server_auth_info_st), 1)) < 0) { gnutls_assert (); return ret; } info = _gnutls_get_auth_info (session); username = info->username; _gnutls_str_cpy (username, MAX_SRP_USERNAME, session->security_parameters.extensions.srp_username); ret = _gnutls_srp_pwd_read_entry (session, username, &pwd_entry); if (ret < 0) { gnutls_assert (); return ret; } /* copy from pwd_entry to local variables (actually in session) */ tmp_size = pwd_entry->g.size; if (_gnutls_mpi_scan_nz (&G, pwd_entry->g.data, &tmp_size) < 0) { gnutls_assert (); return GNUTLS_E_MPI_SCAN_FAILED; } tmp_size = pwd_entry->n.size; if (_gnutls_mpi_scan_nz (&N, pwd_entry->n.data, &tmp_size) < 0) { gnutls_assert (); return GNUTLS_E_MPI_SCAN_FAILED; } tmp_size = pwd_entry->v.size; if (_gnutls_mpi_scan_nz (&V, pwd_entry->v.data, &tmp_size) < 0) { gnutls_assert (); return GNUTLS_E_MPI_SCAN_FAILED; } /* Calculate: B = (k*v + g^b) % N */ B = _gnutls_calc_srp_B (&_b, G, N, V); if (B == NULL) { gnutls_assert (); return GNUTLS_E_MEMORY_ERROR; } if (_gnutls_mpi_print (NULL, &n_b, B) != 0) { gnutls_assert (); return GNUTLS_E_MPI_PRINT_FAILED; } /* Allocate size to hold the N, g, s, B */ data_size = (pwd_entry->n.size + 2 + pwd_entry->g.size + 2 + pwd_entry->salt.size + 1) + (n_b + 2); (*data) = gnutls_malloc (data_size); if ((*data) == NULL) { gnutls_assert (); return GNUTLS_E_MEMORY_ERROR; } /* copy N (mod n) */ data_n = *data; _gnutls_write_datum16 (data_n, pwd_entry->n); /* copy G (generator) to data */ data_g = &data_n[2 + pwd_entry->n.size]; _gnutls_write_datum16 (data_g, pwd_entry->g); /* copy the salt */ data_s = &data_g[2 + pwd_entry->g.size]; _gnutls_write_datum8 (data_s, pwd_entry->salt); /* Copy the B value */ data_b = &data_s[1 + pwd_entry->salt.size]; if (_gnutls_mpi_print (&data_b[2], &n_b, B) != 0) { gnutls_assert(); return GNUTLS_E_MPI_PRINT_FAILED; } _gnutls_write_uint16 (n_b, data_b); _gnutls_hard_log ("INT: SRP B[%d]: %s\n", n_b, _gnutls_bin2hex (&data_b[2], n_b, buf, sizeof (buf))); _gnutls_srp_entry_free (pwd_entry); return data_size; }
/*- * _gnutls_free_auth_info - Frees the auth info structure * @session: is a #gnutls_session_t structure. * * This function frees the auth info structure and sets it to * null. It must be called since some structures contain malloced * elements. -*/ void _gnutls_free_auth_info(gnutls_session_t session) { dh_info_st *dh_info; if (session == NULL) { gnutls_assert(); return; } switch (session->key.auth_info_type) { case GNUTLS_CRD_SRP: break; case GNUTLS_CRD_ANON: { anon_auth_info_t info = _gnutls_get_auth_info(session, GNUTLS_CRD_ANON); if (info == NULL) break; dh_info = &info->dh; _gnutls_free_dh_info(dh_info); } break; case GNUTLS_CRD_PSK: { psk_auth_info_t info = _gnutls_get_auth_info(session, GNUTLS_CRD_PSK); if (info == NULL) break; dh_info = &info->dh; _gnutls_free_dh_info(dh_info); } break; case GNUTLS_CRD_CERTIFICATE: { unsigned int i; cert_auth_info_t info = _gnutls_get_auth_info(session, GNUTLS_CRD_CERTIFICATE); if (info == NULL) break; dh_info = &info->dh; for (i = 0; i < info->ncerts; i++) { _gnutls_free_datum(&info-> raw_certificate_list [i]); } gnutls_free(info->raw_certificate_list); info->raw_certificate_list = NULL; info->ncerts = 0; _gnutls_free_dh_info(dh_info); } break; default: return; } gnutls_free(session->key.auth_info); session->key.auth_info = NULL; session->key.auth_info_size = 0; session->key.auth_info_type = 0; }