/** * gnutls_psk_set_client_credentials - Used to set the username/password, in a gnutls_psk_client_credentials_t structure * @res: is a #gnutls_psk_client_credentials_t structure. * @username: is the user's zero-terminated userid * @key: is the user's key * @format: indicate the format of the key, either * %GNUTLS_PSK_KEY_RAW or %GNUTLS_PSK_KEY_HEX. * * This function sets the username and password, in a * gnutls_psk_client_credentials_t structure. Those will be used in * PSK authentication. @username should be an ASCII string or UTF-8 * strings prepared using the "SASLprep" profile of "stringprep". * The key can be either in raw byte format or in Hex (not with the * '0x' prefix). * * Returns: %GNUTLS_E_SUCCESS on success, or an error code. **/ int gnutls_psk_set_client_credentials (gnutls_psk_client_credentials_t res, const char *username, const gnutls_datum_t * key, gnutls_psk_key_flags flags) { int ret; if (username == NULL || key == NULL || key->data == NULL) { gnutls_assert (); return GNUTLS_E_INVALID_REQUEST; } ret = _gnutls_set_datum (&res->username, username, strlen (username)); if (ret < 0) return ret; if (flags == GNUTLS_PSK_KEY_RAW) { if (_gnutls_set_datum (&res->key, key->data, key->size) < 0) { gnutls_assert (); ret = GNUTLS_E_MEMORY_ERROR; goto error; } } else { /* HEX key */ size_t size; size = res->key.size = key->size / 2; res->key.data = gnutls_malloc (size); if (res->key.data == NULL) { gnutls_assert (); ret = GNUTLS_E_MEMORY_ERROR; goto error; } ret = gnutls_hex_decode (key, (char *) res->key.data, &size); res->key.size = (unsigned int) size; if (ret < 0) { gnutls_assert (); goto error; } } return 0; error: _gnutls_free_datum (&res->username); return ret; }
/** * gnutls_dh_get_group: * @session: is a gnutls session * @raw_gen: will hold the generator. * @raw_prime: will hold the prime. * * This function will return the group parameters used in the last * Diffie-Hellman key exchange with the peer. These are the prime and * the generator used. 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_group(gnutls_session_t session, gnutls_datum_t * raw_gen, gnutls_datum_t * raw_prime) { dh_info_st *dh; int ret; anon_auth_info_t anon_info; cert_auth_info_t cert_info; psk_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; } ret = _gnutls_set_datum(raw_prime, dh->prime.data, dh->prime.size); if (ret < 0) { gnutls_assert(); return ret; } ret = _gnutls_set_datum(raw_gen, dh->generator.data, dh->generator.size); if (ret < 0) { gnutls_assert(); _gnutls_free_datum(raw_prime); return ret; } return 0; }
/** * gnutls_pkcs12_bag_set_key_id: * @bag: The bag * @indx: The bag's element to add the id * @id: the ID * * This function will add the given key ID, to the specified, by the * index, bag element. The key ID will be encoded as a 'Local key * identifier' bag attribute, which is usually used to distinguish * the local private key and the certificate pair. * * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a * negative error value. or a negative error code on error. **/ int gnutls_pkcs12_bag_set_key_id(gnutls_pkcs12_bag_t bag, unsigned indx, const gnutls_datum_t * id) { int ret; if (bag == NULL) { gnutls_assert(); return GNUTLS_E_INVALID_REQUEST; } if (indx > bag->bag_elements - 1) { gnutls_assert(); return GNUTLS_E_INVALID_REQUEST; } ret = _gnutls_set_datum(&bag->element[indx].local_key_id, id->data, id->size); if (ret < 0) { gnutls_assert(); return ret; } return 0; }
/** * gnutls_session_set_data: * @session: is a #gnutls_session_t type. * @session_data: is a pointer to space to hold the session. * @session_data_size: is the session's size * * Sets all session parameters, in order to resume a previously * established session. The session data given must be the one * returned by gnutls_session_get_data(). This function should be * called before gnutls_handshake(). * * Keep in mind that session resuming is advisory. The server may * choose not to resume the session, thus a full handshake will be * performed. * * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise * an error code is returned. **/ int gnutls_session_set_data(gnutls_session_t session, const void *session_data, size_t session_data_size) { int ret; gnutls_datum_t psession; psession.data = (uint8_t *) session_data; psession.size = session_data_size; if (session_data == NULL || session_data_size == 0) { gnutls_assert(); return GNUTLS_E_INVALID_REQUEST; } ret = _gnutls_session_unpack(session, &psession); if (ret < 0) { gnutls_assert(); return ret; } session->internals.resumption_requested = 1; if (session->internals.resumption_data.data != NULL) gnutls_free(session->internals.resumption_data.data); _gnutls_set_datum(&session->internals.resumption_data, session_data, session_data_size); return 0; }
/** * gnutls_session_get_data2: * @session: is a #gnutls_session_t type. * @data: is a pointer to a datum that will hold the session. * * Returns all session parameters needed to be stored to support resumption. * The client should call this, and store the returned session data. A session * may be resumed later by calling gnutls_session_set_data(). * * The returned @data are allocated and must be released using gnutls_free(). * * This function will fail if called prior to handshake completion. In * case of false start TLS, the handshake completes only after data have * been successfully received from the peer. * * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise * an error code is returned. **/ int gnutls_session_get_data2(gnutls_session_t session, gnutls_datum_t *data) { int ret; if (data == NULL) { return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); } if (gnutls_session_is_resumed(session) && session->internals.resumption_data.data) { ret = _gnutls_set_datum(data, session->internals.resumption_data.data, session->internals.resumption_data.size); if (ret < 0) return gnutls_assert_val(ret); return 0; } if (session->internals.resumable == RESUME_FALSE) return GNUTLS_E_INVALID_SESSION; ret = _gnutls_session_pack(session, data); if (ret < 0) { gnutls_assert(); return ret; } return 0; }
/* Reads the DER signed data from the certificate and allocates space and * returns them into signed_data. */ int _gnutls_x509_get_signed_data(ASN1_TYPE src, const gnutls_datum *der, const char *src_name, gnutls_datum_t * signed_data) { int start, end, result; if (der == NULL || der->size == 0) { return _gnutls_x509_der_encode(src, src_name, signed_data, 0); } /* Get the signed data */ result = asn1_der_decoding_startEnd(src, der->data, der->size, src_name, &start, &end); if (result != ASN1_SUCCESS) { result = _gnutls_asn2err(result); gnutls_assert(); goto cleanup; } result = _gnutls_set_datum(signed_data, &der->data[start], end - start + 1); if (result < 0) { gnutls_assert(); goto cleanup; } result = 0; cleanup: return result; }
/** * gnutls_x509_crl_get_raw_issuer_dn: * @crl: should contain a gnutls_x509_crl_t structure * @dn: will hold the starting point of the DN * * This function will return a pointer to the DER encoded DN structure * and the length. * * Returns: a negative error code on error, and (0) on success. * * Since: 2.12.0 **/ int gnutls_x509_crl_get_raw_issuer_dn(gnutls_x509_crl_t crl, gnutls_datum_t * dn) { return _gnutls_set_datum(dn, crl->raw_issuer_dn.data, crl->raw_issuer_dn.size); }
int _gnutls13_recv_session_ticket(gnutls_session_t session, gnutls_buffer_st *buf) { int ret; uint8_t value; tls13_ticket_st *ticket = &session->internals.tls13_ticket; gnutls_datum_t t; size_t val; if (unlikely(buf == NULL)) return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); _gnutls_free_datum(&ticket->ticket); memset(ticket, 0, sizeof(tls13_ticket_st)); _gnutls_handshake_log("HSK[%p]: parsing session ticket message\n", session); /* ticket_lifetime */ ret = _gnutls_buffer_pop_prefix32(buf, &val, 0); if (ret < 0) return gnutls_assert_val(ret); ticket->lifetime = val; /* ticket_age_add */ ret = _gnutls_buffer_pop_prefix32(buf, &val, 0); if (ret < 0) return gnutls_assert_val(ret); ticket->age_add = val; /* ticket_nonce */ ret = _gnutls_buffer_pop_prefix8(buf, &value, 0); if (ret < 0) return gnutls_assert_val(ret); ticket->nonce_size = value; ret = _gnutls_buffer_pop_data(buf, ticket->nonce, ticket->nonce_size); if (ret < 0) return gnutls_assert_val(ret); /* ticket */ ret = _gnutls_buffer_pop_datum_prefix16(buf, &t); if (ret < 0) return gnutls_assert_val(ret); gnutls_free(ticket->ticket.data); ret = _gnutls_set_datum(&ticket->ticket, t.data, t.size); if (ret < 0) return gnutls_assert_val(ret); /* Extensions */ ret = _gnutls_extv_parse(session, parse_nst_extension, buf->data, buf->length); if (ret < 0) return gnutls_assert_val(ret); /* Record the ticket arrival time */ gnutls_gettime(&ticket->arrival_time); return 0; }
int _gnutls_pk_params_copy(gnutls_pk_params_st * dst, const gnutls_pk_params_st * src) { unsigned int i, j; dst->params_nr = 0; if (src == NULL || src->params_nr == 0) { gnutls_assert(); return GNUTLS_E_INVALID_REQUEST; } dst->flags = src->flags; dst->algo = src->algo; for (i = 0; i < src->params_nr; i++) { dst->params[i] = _gnutls_mpi_copy(src->params[i]); if (dst->params[i] == NULL) { goto fail; } dst->params_nr++; } if (_gnutls_set_datum(&dst->raw_priv, src->raw_priv.data, src->raw_priv.size) < 0) { gnutls_assert(); goto fail; } if (_gnutls_set_datum(&dst->raw_pub, src->raw_pub.data, src->raw_pub.size) < 0) { gnutls_assert(); goto fail; } if (src->seed_size) { dst->seed_size = src->seed_size; memcpy(dst->seed, src->seed, src->seed_size); } return 0; fail: for (j = 0; j < i; j++) _gnutls_mpi_release(&dst->params[j]); return GNUTLS_E_MEMORY_ERROR; }
/** * gnutls_x509_crl_get_raw_issuer_dn: * @crl: should contain a gnutls_x509_crl_t structure * @dn: will hold the starting point of the DN * * This function will return a pointer to the DER encoded DN structure * and the length. * * Returns: a negative error code on error, and (0) on success. * * Since: 2.12.0 **/ int gnutls_x509_crl_get_raw_issuer_dn(gnutls_x509_crl_t crl, gnutls_datum_t * dn) { if (crl->raw_issuer_dn.size != 0) { return _gnutls_set_datum(dn, crl->raw_issuer_dn.data, crl->raw_issuer_dn.size); } else { return _gnutls_x509_get_raw_field(crl->crl, "tbsCertList.issuer.rdnSequence", dn); } }
static int name_constraints_add(gnutls_x509_name_constraints_t nc, gnutls_x509_subject_alt_name_t type, const gnutls_datum_t * name, unsigned permitted) { struct name_constraints_node_st * tmp, *prev = NULL; int ret; if (type != GNUTLS_SAN_DNSNAME && type != GNUTLS_SAN_RFC822NAME && type != GNUTLS_SAN_DN && type != GNUTLS_SAN_URI && type != GNUTLS_SAN_IPADDRESS) return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); if (type == GNUTLS_SAN_IPADDRESS && (name->size != 8 && name->size != 32)) { return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); } if (permitted != 0) prev = tmp = nc->permitted; else prev = tmp = nc->excluded; while(tmp != NULL) { tmp = tmp->next; if (tmp != NULL) prev = tmp; } tmp = gnutls_malloc(sizeof(struct name_constraints_node_st)); if (tmp == NULL) return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); tmp->next = NULL; tmp->type = type; ret = _gnutls_set_datum(&tmp->name, name->data, name->size); if (ret < 0) { gnutls_assert(); gnutls_free(tmp); return ret; } if (prev == NULL) { if (permitted != 0) nc->permitted = tmp; else nc->excluded = tmp; } else prev->next = tmp; return 0; }
/** * gnutls_pkcs12_bag_set_data - This function inserts data into the bag * @bag: The bag * @type: The data's type * @data: the data to be copied. * * This function will insert the given data of the given type into the * bag. * * Returns the index of the added bag on success, or a negative * value on error. * **/ int gnutls_pkcs12_bag_set_data (gnutls_pkcs12_bag_t bag, gnutls_pkcs12_bag_type_t type, const gnutls_datum_t * data) { int ret; if (bag == NULL) { gnutls_assert (); return GNUTLS_E_INVALID_REQUEST; } if (bag->bag_elements == MAX_BAG_ELEMENTS - 1) { gnutls_assert (); /* bag is full */ return GNUTLS_E_MEMORY_ERROR; } if (bag->bag_elements == 1) { /* A bag with a key or an encrypted bag, must have * only one element. */ if (bag->element[0].type == GNUTLS_BAG_PKCS8_KEY || bag->element[0].type == GNUTLS_BAG_PKCS8_ENCRYPTED_KEY || bag->element[0].type == GNUTLS_BAG_ENCRYPTED) { gnutls_assert (); return GNUTLS_E_INVALID_REQUEST; } } ret = _gnutls_set_datum (&bag->element[bag->bag_elements].data, data->data, data->size); if (ret < 0) { gnutls_assert (); return ret; } bag->element[bag->bag_elements].type = type; bag->bag_elements++; return bag->bag_elements - 1; }
/* Reads the DER signed data from the certificate and allocates space and * returns them into signed_data. */ int _gnutls_x509_get_signed_data(ASN1_TYPE src, const gnutls_datum *_der, const char *src_name, gnutls_datum_t * signed_data) { int start, end, result; gnutls_datum_t der; unsigned need_free = 0; if (_der == NULL || _der->size == 0) { result = _gnutls_x509_der_encode(src, "", &der, 0); if (result < 0) { gnutls_assert(); return result; } need_free = 1; } else { der.data = _der->data; der.size = _der->size; } /* Get the signed data */ result = asn1_der_decoding_startEnd(src, der.data, der.size, src_name, &start, &end); if (result != ASN1_SUCCESS) { result = _gnutls_asn2err(result); gnutls_assert(); goto cleanup; } result = _gnutls_set_datum(signed_data, &der.data[start], end - start + 1); if (result < 0) { gnutls_assert(); goto cleanup; } result = 0; cleanup: if (need_free != 0) _gnutls_free_datum(&der); return result; }
/** * gnutls_srp_set_server_fake_salt_seed: * @cred: is a #gnutls_srp_server_credentials_t type * @seed: is the seed data, only needs to be valid until the function * returns; size of the seed must be greater than zero * @salt_length: is the length of the generated fake salts * * This function sets the seed that is used to generate salts for * invalid (non-existent) usernames. * * In order to prevent attackers from guessing valid usernames, * when a user does not exist gnutls generates a salt and a verifier * and proceeds with the protocol as usual. * The authentication will ultimately fail, but the client cannot tell * whether the username is valid (exists) or invalid. * * If an attacker learns the seed, given a salt (which is part of the * handshake) which was generated when the seed was in use, it can tell * whether or not the authentication failed because of an unknown username. * This seed cannot be used to reveal application data or passwords. * * @salt_length should represent the salt length your application uses. * Generating fake salts longer than 20 bytes is not supported. * * By default the seed is a random value, different each time a * #gnutls_srp_server_credentials_t is allocated and fake salts are * 16 bytes long. * * Since: 3.3.0 **/ void gnutls_srp_set_server_fake_salt_seed(gnutls_srp_server_credentials_t cred, const gnutls_datum_t * seed, unsigned int salt_length) { _gnutls_free_datum(&cred->fake_salt_seed); _gnutls_set_datum(&cred->fake_salt_seed, seed->data, seed->size); /* Cap the salt length at the output size of the MAC algorithm * we are using to generate the fake salts. */ const mac_entry_st * me = mac_to_entry(SRP_FAKE_SALT_MAC); const size_t mac_len = me->output_size; cred->fake_salt_length = (salt_length < mac_len ? salt_length : mac_len); }
/** * 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); }
/* Reads the DER signed data from the certificate and allocates space and * returns them into signed_data. */ int _gnutls_x509_get_signed_data (ASN1_TYPE src, const char *src_name, gnutls_datum_t * signed_data) { gnutls_datum_t der; int start, end, result; result = _gnutls_x509_der_encode (src, "", &der, 0); if (result < 0) { gnutls_assert (); return result; } /* Get the signed data */ result = asn1_der_decoding_startEnd (src, der.data, der.size, src_name, &start, &end); if (result != ASN1_SUCCESS) { result = _gnutls_asn2err (result); gnutls_assert (); goto cleanup; } result = _gnutls_set_datum (signed_data, &der.data[start], end - start + 1); if (result < 0) { gnutls_assert (); goto cleanup; } result = 0; cleanup: _gnutls_free_datum (&der); return result; }
/*- * _gnutls_x509_crl_get_raw_issuer_dn - This function returns the issuer's DN DER encoded * @crl: should contain a gnutls_x509_crl_t structure * @dn: will hold the starting point of the DN * * This function will return a pointer to the DER encoded DN structure and * the length. * * Returns a negative value on error, and zero on success. * -*/ int _gnutls_x509_crl_get_raw_issuer_dn (gnutls_x509_crl_t crl, gnutls_datum_t * dn) { ASN1_TYPE c2 = ASN1_TYPE_EMPTY; int result, len1; int start1, end1; gnutls_datum_t crl_signed_data; if (crl == NULL) { gnutls_assert (); return GNUTLS_E_INVALID_REQUEST; } /* get the issuer of 'crl' */ if ((result = asn1_create_element (_gnutls_get_pkix (), "PKIX1.TBSCertList", &c2)) != ASN1_SUCCESS) { gnutls_assert (); return _gnutls_asn2err (result); } result = _gnutls_x509_get_signed_data (crl->crl, "tbsCertList", &crl_signed_data); if (result < 0) { gnutls_assert (); goto cleanup; } result = asn1_der_decoding (&c2, crl_signed_data.data, crl_signed_data.size, NULL); if (result != ASN1_SUCCESS) { /* couldn't decode DER */ gnutls_assert (); asn1_delete_structure (&c2); result = _gnutls_asn2err (result); goto cleanup; } result = asn1_der_decoding_startEnd (c2, crl_signed_data.data, crl_signed_data.size, "issuer", &start1, &end1); if (result != ASN1_SUCCESS) { gnutls_assert (); result = _gnutls_asn2err (result); goto cleanup; } len1 = end1 - start1 + 1; _gnutls_set_datum (dn, &crl_signed_data.data[start1], len1); result = 0; cleanup: asn1_delete_structure (&c2); _gnutls_free_datum (&crl_signed_data); return result; }
static int parse_cert_list(gnutls_session_t session, uint8_t * data, size_t data_size) { int len, ret; uint8_t *p = data; cert_auth_info_t info; gnutls_certificate_credentials_t cred; ssize_t dsize = data_size, size; int i; unsigned npeer_certs, npeer_ocsp, j; crt_cert_ctx_st ctx; gnutls_datum_t *peer_certs = NULL; gnutls_datum_t *peer_ocsp = NULL; unsigned nentries = 0; cred = (gnutls_certificate_credentials_t) _gnutls_get_cred(session, GNUTLS_CRD_CERTIFICATE); if (cred == NULL) { gnutls_assert(); return GNUTLS_E_INSUFFICIENT_CREDENTIALS; } if ((ret = _gnutls_auth_info_init(session, GNUTLS_CRD_CERTIFICATE, sizeof(cert_auth_info_st), 1)) < 0) { gnutls_assert(); return ret; } if (data == NULL || data_size == 0) { /* no certificate was sent */ return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH); } info = _gnutls_get_auth_info(session, GNUTLS_CRD_CERTIFICATE); if (info == NULL) return gnutls_assert_val(GNUTLS_E_INSUFFICIENT_CREDENTIALS); DECR_LEN(dsize, 3); size = _gnutls_read_uint24(p); p += 3; if (size != dsize) return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH); if (size == 0) return gnutls_assert_val(GNUTLS_E_NO_CERTIFICATE_FOUND); i = dsize; while (i > 0) { DECR_LEN(dsize, 3); len = _gnutls_read_uint24(p); if (len == 0) return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH); DECR_LEN(dsize, len); p += len + 3; i -= len + 3; DECR_LEN(dsize, 2); len = _gnutls_read_uint16(p); DECR_LEN(dsize, len); i -= len + 2; p += len + 2; nentries++; } if (dsize != 0) return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH); /* this is unnecessary - keeping to avoid a regression due to a re-org * of the loop above */ if (nentries == 0) return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH); npeer_ocsp = 0; npeer_certs = 0; /* Ok we now allocate the memory to hold the * certificate list */ peer_certs = gnutls_calloc(nentries, sizeof(gnutls_datum_t)); if (peer_certs == NULL) return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); peer_ocsp = gnutls_calloc(nentries, sizeof(gnutls_datum_t)); if (peer_ocsp == NULL) { ret = gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); goto cleanup; } p = data+3; /* Now we start parsing the list (again). * We don't use DECR_LEN since the list has * been parsed before. */ ctx.session = session; for (j = 0; j < nentries; j++) { len = _gnutls_read_uint24(p); p += 3; ret = _gnutls_set_datum(&peer_certs[j], p, len); if (ret < 0) { gnutls_assert(); ret = GNUTLS_E_CERTIFICATE_ERROR; goto cleanup; } npeer_certs++; p += len; len = _gnutls_read_uint16(p); ctx.ocsp = &peer_ocsp[j]; ctx.idx = j; ret = _gnutls_extv_parse(&ctx, parse_cert_extension, p, len+2); if (ret < 0) { gnutls_assert(); goto cleanup; } p += len+2; npeer_ocsp++; } /* The OCSP entries match the certificate entries, although * the contents of each OCSP entry may be NULL. */ for(j=0;j<info->ncerts;j++) gnutls_free(info->raw_certificate_list[j].data); gnutls_free(info->raw_certificate_list); for(j=0;j<info->nocsp;j++) gnutls_free(info->raw_ocsp_list[j].data); gnutls_free(info->raw_ocsp_list); info->raw_certificate_list = peer_certs; info->ncerts = npeer_certs; info->raw_ocsp_list = peer_ocsp; info->nocsp = npeer_ocsp; return 0; cleanup: for(j=0;j<npeer_certs;j++) gnutls_free(peer_certs[j].data); for(j=0;j<npeer_ocsp;j++) gnutls_free(peer_ocsp[j].data); gnutls_free(peer_certs); gnutls_free(peer_ocsp); return ret; }
/** * cdk_pk_verify: * @pk: the public key * @sig: signature * @md: the message digest * * Verify the signature in @sig and compare it with the message digest in @md. **/ cdk_error_t cdk_pk_verify(cdk_pubkey_t pk, cdk_pkt_signature_t sig, const byte * md) { gnutls_datum_t s_sig = { NULL, 0 }, di = { NULL, 0}; byte *encmd = NULL; cdk_error_t rc; int ret, algo; unsigned int i; gnutls_pk_params_st params; const mac_entry_st *me; if (!pk || !sig || !md) { gnutls_assert(); return CDK_Inv_Value; } if (is_DSA(pk->pubkey_algo)) algo = GNUTLS_PK_DSA; else if (is_RSA(pk->pubkey_algo)) algo = GNUTLS_PK_RSA; else { gnutls_assert(); return CDK_Inv_Value; } rc = sig_to_datum(&s_sig, sig); if (rc) { gnutls_assert(); goto leave; } me = mac_to_entry(sig->digest_algo); rc = _gnutls_set_datum(&di, md, _gnutls_hash_get_algo_len(me)); if (rc < 0) { rc = gnutls_assert_val(CDK_Out_Of_Core); goto leave; } rc = pk_prepare_hash(algo, me, &di); if (rc < 0) { rc = gnutls_assert_val(CDK_General_Error); goto leave; } params.params_nr = cdk_pk_get_npkey(pk->pubkey_algo); for (i = 0; i < params.params_nr; i++) params.params[i] = pk->mpi[i]; params.flags = 0; ret = _gnutls_pk_verify(algo, &di, &s_sig, ¶ms); if (ret < 0) { gnutls_assert(); rc = map_gnutls_error(ret); goto leave; } rc = 0; leave: _gnutls_free_datum(&s_sig); _gnutls_free_datum(&di); cdk_free(encmd); return rc; }
/* This will create a PKCS1 or DSA signature, as defined in the TLS protocol. * Cert is the certificate of the corresponding private key. It is only checked if * it supports signing. */ static int sign_tls_hash(gnutls_session_t session, const mac_entry_st * hash_algo, gnutls_pcert_st * cert, gnutls_privkey_t pkey, const gnutls_datum_t * hash_concat, gnutls_datum_t * signature) { const version_entry_st *ver = get_version(session); unsigned int key_usage = 0; /* If our certificate supports signing */ if (cert != NULL) { gnutls_pubkey_get_key_usage(cert->pubkey, &key_usage); if (key_usage != 0) if (!(key_usage & GNUTLS_KEY_DIGITAL_SIGNATURE)) { gnutls_assert(); _gnutls_audit_log(session, "Peer's certificate does not allow digital signatures. Key usage violation detected (ignored).\n"); } /* External signing. Deprecated. To be removed. */ if (!pkey) { int ret; if (!session->internals.sign_func) return gnutls_assert_val (GNUTLS_E_INSUFFICIENT_CREDENTIALS); if (!_gnutls_version_has_selectable_sighash(ver)) return (*session->internals.sign_func) (session, session->internals.sign_func_userdata, cert->type, &cert->cert, hash_concat, signature); else { gnutls_datum_t digest; ret = _gnutls_set_datum(&digest, hash_concat->data, hash_concat->size); if (ret < 0) return gnutls_assert_val(ret); ret = pk_prepare_hash (gnutls_pubkey_get_pk_algorithm (cert->pubkey, NULL), hash_algo, &digest); if (ret < 0) { gnutls_assert(); goto es_cleanup; } ret = (*session->internals.sign_func) (session, session->internals.sign_func_userdata, cert->type, &cert->cert, &digest, signature); es_cleanup: gnutls_free(digest.data); return ret; } } } if (!_gnutls_version_has_selectable_sighash(ver)) return gnutls_privkey_sign_raw_data(pkey, 0, hash_concat, signature); else return gnutls_privkey_sign_hash(pkey, (gnutls_digest_algorithm_t)hash_algo->id, 0, hash_concat, signature); }
static int unpack_psk_auth_info (gnutls_session_t session, const gnutls_datum_t * packed_session) { size_t username_size; size_t pack_size; int pos = 0, size, ret; psk_auth_info_t info; if (packed_session->data[0] != GNUTLS_CRD_PSK) { gnutls_assert (); return GNUTLS_E_INVALID_REQUEST; } pack_size = _gnutls_read_uint32 (&packed_session->data[PACK_HEADER_SIZE]); pos += PACK_HEADER_SIZE + 4; if (pack_size == 0) return 0; /* nothing to be done */ /* a simple check for integrity */ if (pack_size + PACK_HEADER_SIZE + 4 > packed_session->size) { gnutls_assert (); return GNUTLS_E_INVALID_REQUEST; } /* client and serer have the same auth_info here */ 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; } username_size = _gnutls_read_uint32 (&packed_session->data[pos]); pos += 4; memcpy (info->username, &packed_session->data[pos], username_size); pos += username_size; info->dh.secret_bits = _gnutls_read_uint16 (&packed_session->data[pos]); pos += 2; size = _gnutls_read_uint32 (&packed_session->data[pos]); pos += 4; ret = _gnutls_set_datum (&info->dh.prime, &packed_session->data[pos], size); if (ret < 0) { gnutls_assert (); goto error; } pos += size; size = _gnutls_read_uint32 (&packed_session->data[pos]); pos += 4; ret = _gnutls_set_datum (&info->dh.generator, &packed_session->data[pos], size); if (ret < 0) { gnutls_assert (); goto error; } pos += size; size = _gnutls_read_uint32 (&packed_session->data[pos]); pos += 4; ret = _gnutls_set_datum (&info->dh.public_key, &packed_session->data[pos], size); if (ret < 0) { gnutls_assert (); goto error; } pos += size; return 0; error: _gnutls_free_datum (&info->dh.prime); _gnutls_free_datum (&info->dh.generator); _gnutls_free_datum (&info->dh.public_key); return ret; }
static int client_send_params(gnutls_session_t session, gnutls_buffer_t extdata, const gnutls_psk_client_credentials_t cred) { int ret, ext_offset = 0; uint8_t binder_value[MAX_HASH_SIZE]; size_t spos; gnutls_datum_t username = {NULL, 0}; gnutls_datum_t user_key = {NULL, 0}, rkey = {NULL, 0}; gnutls_datum_t client_hello; unsigned next_idx; const mac_entry_st *prf_res = NULL; const mac_entry_st *prf_psk = NULL; struct timespec cur_time; uint32_t ticket_age, ob_ticket_age; int free_username = 0; psk_auth_info_t info = NULL; unsigned psk_id_len = 0; unsigned binders_len, binders_pos; if (((session->internals.flags & GNUTLS_NO_TICKETS) || session->internals.tls13_ticket.ticket.data == NULL) && (!cred || !_gnutls_have_psk_credentials(cred, session))) { return 0; } binders_len = 0; /* placeholder to be filled later */ spos = extdata->length; ret = _gnutls_buffer_append_prefix(extdata, 16, 0); if (ret < 0) return gnutls_assert_val(ret); /* First, let's see if we have a session ticket to send */ if (!(session->internals.flags & GNUTLS_NO_TICKETS) && session->internals.tls13_ticket.ticket.data != NULL) { /* We found a session ticket */ if (unlikely(session->internals.tls13_ticket.prf == NULL)) { _gnutls13_session_ticket_unset(session); ret = gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); goto cleanup; } prf_res = session->internals.tls13_ticket.prf; gnutls_gettime(&cur_time); if (unlikely(_gnutls_timespec_cmp(&cur_time, &session->internals. tls13_ticket. arrival_time) < 0)) { gnutls_assert(); _gnutls13_session_ticket_unset(session); goto ignore_ticket; } /* Check whether the ticket is stale */ ticket_age = timespec_sub_ms(&cur_time, &session->internals.tls13_ticket. arrival_time); if (ticket_age / 1000 > session->internals.tls13_ticket.lifetime) { _gnutls13_session_ticket_unset(session); goto ignore_ticket; } ret = compute_psk_from_ticket(&session->internals.tls13_ticket, &rkey); if (ret < 0) { _gnutls13_session_ticket_unset(session); goto ignore_ticket; } /* Calculate obfuscated ticket age, in milliseconds, mod 2^32 */ ob_ticket_age = ticket_age + session->internals.tls13_ticket.age_add; if ((ret = _gnutls_buffer_append_data_prefix(extdata, 16, session->internals.tls13_ticket.ticket.data, session->internals.tls13_ticket.ticket.size)) < 0) { gnutls_assert(); goto cleanup; } /* Now append the obfuscated ticket age */ if ((ret = _gnutls_buffer_append_prefix(extdata, 32, ob_ticket_age)) < 0) { gnutls_assert(); goto cleanup; } psk_id_len += 6 + session->internals.tls13_ticket.ticket.size; binders_len += 1 + _gnutls_mac_get_algo_len(prf_res); } ignore_ticket: if (cred && _gnutls_have_psk_credentials(cred, session)) { gnutls_datum_t tkey; if (cred->binder_algo == NULL) { gnutls_assert(); ret = gnutls_assert_val(GNUTLS_E_INSUFFICIENT_CREDENTIALS); goto cleanup; } prf_psk = cred->binder_algo; ret = _gnutls_find_psk_key(session, cred, &username, &tkey, &free_username); if (ret < 0) { gnutls_assert(); goto cleanup; } if (username.size == 0 || username.size > UINT16_MAX) { ret = gnutls_assert_val(GNUTLS_E_INVALID_PASSWORD); goto cleanup; } if (!free_username) { /* we need to copy the key */ ret = _gnutls_set_datum(&user_key, tkey.data, tkey.size); if (ret < 0) { gnutls_assert(); goto cleanup; } } else { user_key.data = tkey.data; user_key.size = tkey.size; } ret = _gnutls_auth_info_init(session, GNUTLS_CRD_PSK, sizeof(psk_auth_info_st), 1); if (ret < 0) { gnutls_assert(); goto cleanup; } info = _gnutls_get_auth_info(session, GNUTLS_CRD_PSK); assert(info != NULL); memcpy(info->username, username.data, username.size); info->username[username.size] = 0; if ((ret = _gnutls_buffer_append_data_prefix(extdata, 16, username.data, username.size)) < 0) { gnutls_assert(); goto cleanup; } /* Now append the obfuscated ticket age */ if ((ret = _gnutls_buffer_append_prefix(extdata, 32, 0)) < 0) { gnutls_assert(); goto cleanup; } psk_id_len += 6 + username.size; binders_len += 1 + _gnutls_mac_get_algo_len(prf_psk); } /* if no tickets or identities to be sent */ if (psk_id_len == 0) { /* reset extensions buffer */ extdata->length = spos; return 0; } _gnutls_write_uint16(psk_id_len, &extdata->data[spos]); binders_pos = extdata->length-spos; ext_offset = _gnutls_ext_get_extensions_offset(session); /* Compute the binders. extdata->data points to the start * of this client hello. */ assert(extdata->length >= sizeof(mbuffer_st)); assert(ext_offset >= (ssize_t)sizeof(mbuffer_st)); ext_offset -= sizeof(mbuffer_st); client_hello.data = extdata->data+sizeof(mbuffer_st); client_hello.size = extdata->length-sizeof(mbuffer_st); next_idx = 0; ret = _gnutls_buffer_append_prefix(extdata, 16, binders_len); if (ret < 0) { gnutls_assert_val(ret); goto cleanup; } if (prf_res && rkey.size > 0) { ret = compute_psk_binder(session, prf_res, binders_len, binders_pos, ext_offset, &rkey, &client_hello, 1, binder_value); if (ret < 0) { gnutls_assert(); goto cleanup; } /* Associate the selected pre-shared key with the session */ gnutls_free(session->key.binders[next_idx].psk.data); session->key.binders[next_idx].psk.data = rkey.data; session->key.binders[next_idx].psk.size = rkey.size; rkey.data = NULL; session->key.binders[next_idx].prf = prf_res; session->key.binders[next_idx].resumption = 1; session->key.binders[next_idx].idx = next_idx; _gnutls_handshake_log("EXT[%p]: sent PSK resumption identity (%d)\n", session, next_idx); next_idx++; /* Add the binder */ ret = _gnutls_buffer_append_data_prefix(extdata, 8, binder_value, prf_res->output_size); if (ret < 0) { gnutls_assert(); goto cleanup; } session->internals.hsk_flags |= HSK_TLS13_TICKET_SENT; } if (prf_psk && user_key.size > 0 && info) { ret = compute_psk_binder(session, prf_psk, binders_len, binders_pos, ext_offset, &user_key, &client_hello, 0, binder_value); if (ret < 0) { gnutls_assert(); goto cleanup; } /* Associate the selected pre-shared key with the session */ gnutls_free(session->key.binders[next_idx].psk.data); session->key.binders[next_idx].psk.data = user_key.data; session->key.binders[next_idx].psk.size = user_key.size; user_key.data = NULL; session->key.binders[next_idx].prf = prf_psk; session->key.binders[next_idx].resumption = 0; session->key.binders[next_idx].idx = next_idx; _gnutls_handshake_log("EXT[%p]: sent PSK identity '%s' (%d)\n", session, info->username, next_idx); next_idx++; /* Add the binder */ ret = _gnutls_buffer_append_data_prefix(extdata, 8, binder_value, prf_psk->output_size); if (ret < 0) { gnutls_assert(); goto cleanup; } } ret = 0; cleanup: if (free_username) _gnutls_free_datum(&username); _gnutls_free_temp_key_datum(&user_key); _gnutls_free_temp_key_datum(&rkey); return ret; }
/* This function is to be called after handshake, when master_secret, * client_random and server_random have been initialized. * This function creates the keys and stores them into pending session. * (session->cipher_specs) */ static int _gnutls_set_keys (gnutls_session_t session, record_parameters_st * params, int hash_size, int IV_size, int key_size, int export_flag) { /* FIXME: This function is too long */ uint8_t rnd[2 * GNUTLS_RANDOM_SIZE]; uint8_t rrnd[2 * GNUTLS_RANDOM_SIZE]; int pos, ret; int block_size; char buf[65]; /* avoid using malloc */ uint8_t key_block[2 * MAX_HASH_SIZE + 2 * MAX_CIPHER_KEY_SIZE + 2 * MAX_CIPHER_BLOCK_SIZE]; record_state_st *client_write, *server_write; if (session->security_parameters.entity == GNUTLS_CLIENT) { client_write = ¶ms->write; server_write = ¶ms->read; } else { client_write = ¶ms->read; server_write = ¶ms->write; } block_size = 2 * hash_size + 2 * key_size; if (export_flag == 0) block_size += 2 * IV_size; memcpy (rnd, session->security_parameters.server_random, GNUTLS_RANDOM_SIZE); memcpy (&rnd[GNUTLS_RANDOM_SIZE], session->security_parameters.client_random, GNUTLS_RANDOM_SIZE); memcpy (rrnd, session->security_parameters.client_random, GNUTLS_RANDOM_SIZE); memcpy (&rrnd[GNUTLS_RANDOM_SIZE], session->security_parameters.server_random, GNUTLS_RANDOM_SIZE); if (session->security_parameters.version == GNUTLS_SSL3) { /* SSL 3 */ ret = _gnutls_ssl3_generate_random (session->security_parameters.master_secret, GNUTLS_MASTER_SIZE, rnd, 2 * GNUTLS_RANDOM_SIZE, block_size, key_block); } else { /* TLS 1.0 */ ret = _gnutls_PRF (session, session->security_parameters.master_secret, GNUTLS_MASTER_SIZE, keyexp, keyexp_length, rnd, 2 * GNUTLS_RANDOM_SIZE, block_size, key_block); } if (ret < 0) return gnutls_assert_val (ret); _gnutls_hard_log ("INT: KEY BLOCK[%d]: %s\n", block_size, _gnutls_bin2hex (key_block, block_size, buf, sizeof (buf), NULL)); pos = 0; if (hash_size > 0) { if (_gnutls_set_datum (&client_write->mac_secret, &key_block[pos], hash_size) < 0) return gnutls_assert_val (GNUTLS_E_MEMORY_ERROR); pos += hash_size; if (_gnutls_set_datum (&server_write->mac_secret, &key_block[pos], hash_size) < 0) return gnutls_assert_val (GNUTLS_E_MEMORY_ERROR); pos += hash_size; } if (key_size > 0) { uint8_t key1[EXPORT_FINAL_KEY_SIZE]; uint8_t key2[EXPORT_FINAL_KEY_SIZE]; uint8_t *client_write_key, *server_write_key; int client_write_key_size, server_write_key_size; if (export_flag == 0) { client_write_key = &key_block[pos]; client_write_key_size = key_size; pos += key_size; server_write_key = &key_block[pos]; server_write_key_size = key_size; pos += key_size; } else { /* export */ client_write_key = key1; server_write_key = key2; /* generate the final keys */ if (session->security_parameters.version == GNUTLS_SSL3) { /* SSL 3 */ ret = _gnutls_ssl3_hash_md5 (&key_block[pos], key_size, rrnd, 2 * GNUTLS_RANDOM_SIZE, EXPORT_FINAL_KEY_SIZE, client_write_key); } else { /* TLS 1.0 */ ret = _gnutls_PRF (session, &key_block[pos], key_size, cliwrite, cliwrite_length, rrnd, 2 * GNUTLS_RANDOM_SIZE, EXPORT_FINAL_KEY_SIZE, client_write_key); } if (ret < 0) return gnutls_assert_val (ret); client_write_key_size = EXPORT_FINAL_KEY_SIZE; pos += key_size; if (session->security_parameters.version == GNUTLS_SSL3) { /* SSL 3 */ ret = _gnutls_ssl3_hash_md5 (&key_block[pos], key_size, rnd, 2 * GNUTLS_RANDOM_SIZE, EXPORT_FINAL_KEY_SIZE, server_write_key); } else { /* TLS 1.0 */ ret = _gnutls_PRF (session, &key_block[pos], key_size, servwrite, servwrite_length, rrnd, 2 * GNUTLS_RANDOM_SIZE, EXPORT_FINAL_KEY_SIZE, server_write_key); } if (ret < 0) return gnutls_assert_val (ret); server_write_key_size = EXPORT_FINAL_KEY_SIZE; pos += key_size; } if (_gnutls_set_datum (&client_write->key, client_write_key, client_write_key_size) < 0) return gnutls_assert_val (GNUTLS_E_MEMORY_ERROR); _gnutls_hard_log ("INT: CLIENT WRITE KEY [%d]: %s\n", client_write_key_size, _gnutls_bin2hex (client_write_key, client_write_key_size, buf, sizeof (buf), NULL)); if (_gnutls_set_datum (&server_write->key, server_write_key, server_write_key_size) < 0) return gnutls_assert_val (GNUTLS_E_MEMORY_ERROR); _gnutls_hard_log ("INT: SERVER WRITE KEY [%d]: %s\n", server_write_key_size, _gnutls_bin2hex (server_write_key, server_write_key_size, buf, sizeof (buf), NULL)); } /* IV generation in export and non export ciphers. */ if (IV_size > 0 && export_flag == 0) { if (_gnutls_set_datum (&client_write->IV, &key_block[pos], IV_size) < 0) return gnutls_assert_val (GNUTLS_E_MEMORY_ERROR); pos += IV_size; if (_gnutls_set_datum (&server_write->IV, &key_block[pos], IV_size) < 0) return gnutls_assert_val (GNUTLS_E_MEMORY_ERROR); } else if (IV_size > 0 && export_flag != 0) { uint8_t iv_block[MAX_CIPHER_BLOCK_SIZE * 2]; if (session->security_parameters.version == GNUTLS_SSL3) { /* SSL 3 */ ret = _gnutls_ssl3_hash_md5 ("", 0, rrnd, GNUTLS_RANDOM_SIZE * 2, IV_size, iv_block); if (ret < 0) return gnutls_assert_val (ret); ret = _gnutls_ssl3_hash_md5 ("", 0, rnd, GNUTLS_RANDOM_SIZE * 2, IV_size, &iv_block[IV_size]); } else { /* TLS 1.0 */ ret = _gnutls_PRF (session, (uint8_t*)"", 0, ivblock, ivblock_length, rrnd, 2 * GNUTLS_RANDOM_SIZE, IV_size * 2, iv_block); } if (ret < 0) return gnutls_assert_val (ret); if (_gnutls_set_datum (&client_write->IV, iv_block, IV_size) < 0) return gnutls_assert_val (GNUTLS_E_MEMORY_ERROR); if (_gnutls_set_datum (&server_write->IV, &iv_block[IV_size], IV_size) < 0) return gnutls_assert_val (GNUTLS_E_MEMORY_ERROR); } return 0; }
/** * gnutls_x509_crl_import: * @crl: The structure to store the parsed CRL. * @data: The DER or PEM encoded CRL. * @format: One of DER or PEM * * This function will convert the given DER or PEM encoded CRL * to the native #gnutls_x509_crl_t format. The output will be stored in 'crl'. * * If the CRL is PEM encoded it should have a header of "X509 CRL". * * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a * negative error value. **/ int gnutls_x509_crl_import(gnutls_x509_crl_t crl, const gnutls_datum_t * data, gnutls_x509_crt_fmt_t format) { int result = 0; if (crl == NULL) { gnutls_assert(); return GNUTLS_E_INVALID_REQUEST; } _gnutls_free_datum(&crl->der); /* If the CRL is in PEM format then decode it */ if (format == GNUTLS_X509_FMT_PEM) { result = _gnutls_fbase64_decode(PEM_CRL, data->data, data->size, &crl->der); if (result < 0) { gnutls_assert(); return result; } } else { result = _gnutls_set_datum(&crl->der, data->data, data->size); if (result < 0) { gnutls_assert(); return result; } } if (crl->expanded) { result = crl_reinit(crl); if (result < 0) { gnutls_assert(); goto cleanup; } } crl->expanded = 1; result = asn1_der_decoding(&crl->crl, crl->der.data, crl->der.size, NULL); if (result != ASN1_SUCCESS) { result = _gnutls_asn2err(result); gnutls_assert(); goto cleanup; } result = _gnutls_x509_get_raw_field2(crl->crl, &crl->der, "tbsCertList.issuer.rdnSequence", &crl->raw_issuer_dn); if (result < 0) { gnutls_assert(); goto cleanup; } return 0; cleanup: _gnutls_free_datum(&crl->der); return result; }
/* This function is to be called after handshake, when master_secret, * client_random and server_random have been initialized. * This function creates the keys and stores them into pending session. * (session->cipher_specs) */ static int _gnutls_set_keys(gnutls_session_t session, record_parameters_st * params, int hash_size, int IV_size, int key_size) { /* FIXME: This function is too long */ uint8_t rnd[2 * GNUTLS_RANDOM_SIZE]; uint8_t rrnd[2 * GNUTLS_RANDOM_SIZE]; int pos, ret; int block_size; char buf[65]; /* avoid using malloc */ uint8_t key_block[2 * MAX_HASH_SIZE + 2 * MAX_CIPHER_KEY_SIZE + 2 * MAX_CIPHER_BLOCK_SIZE]; record_state_st *client_write, *server_write; if (session->security_parameters.entity == GNUTLS_CLIENT) { client_write = ¶ms->write; server_write = ¶ms->read; } else { client_write = ¶ms->read; server_write = ¶ms->write; } block_size = 2 * hash_size + 2 * key_size; block_size += 2 * IV_size; memcpy(rnd, session->security_parameters.server_random, GNUTLS_RANDOM_SIZE); memcpy(&rnd[GNUTLS_RANDOM_SIZE], session->security_parameters.client_random, GNUTLS_RANDOM_SIZE); memcpy(rrnd, session->security_parameters.client_random, GNUTLS_RANDOM_SIZE); memcpy(&rrnd[GNUTLS_RANDOM_SIZE], session->security_parameters.server_random, GNUTLS_RANDOM_SIZE); if (get_num_version(session) == GNUTLS_SSL3) { /* SSL 3 */ ret = _gnutls_ssl3_generate_random (session->security_parameters.master_secret, GNUTLS_MASTER_SIZE, rnd, 2 * GNUTLS_RANDOM_SIZE, block_size, key_block); } else { /* TLS 1.0 */ ret = _gnutls_PRF(session, session->security_parameters.master_secret, GNUTLS_MASTER_SIZE, keyexp, keyexp_length, rnd, 2 * GNUTLS_RANDOM_SIZE, block_size, key_block); } if (ret < 0) return gnutls_assert_val(ret); _gnutls_hard_log("INT: KEY BLOCK[%d]: %s\n", block_size, _gnutls_bin2hex(key_block, block_size, buf, sizeof(buf), NULL)); pos = 0; if (hash_size > 0) { if (_gnutls_set_datum (&client_write->mac_secret, &key_block[pos], hash_size) < 0) return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); pos += hash_size; if (_gnutls_set_datum (&server_write->mac_secret, &key_block[pos], hash_size) < 0) return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); pos += hash_size; } if (key_size > 0) { uint8_t *client_write_key, *server_write_key; int client_write_key_size, server_write_key_size; client_write_key = &key_block[pos]; client_write_key_size = key_size; pos += key_size; server_write_key = &key_block[pos]; server_write_key_size = key_size; pos += key_size; if (_gnutls_set_datum (&client_write->key, client_write_key, client_write_key_size) < 0) return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); _gnutls_hard_log("INT: CLIENT WRITE KEY [%d]: %s\n", client_write_key_size, _gnutls_bin2hex(client_write_key, client_write_key_size, buf, sizeof(buf), NULL)); if (_gnutls_set_datum (&server_write->key, server_write_key, server_write_key_size) < 0) return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); _gnutls_hard_log("INT: SERVER WRITE KEY [%d]: %s\n", server_write_key_size, _gnutls_bin2hex(server_write_key, server_write_key_size, buf, sizeof(buf), NULL)); } /* IV generation in export and non export ciphers. */ if (IV_size > 0) { if (_gnutls_set_datum (&client_write->IV, &key_block[pos], IV_size) < 0) return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); pos += IV_size; if (_gnutls_set_datum (&server_write->IV, &key_block[pos], IV_size) < 0) return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); _gnutls_hard_log("INT: CLIENT WRITE IV [%d]: %s\n", client_write->IV.size, _gnutls_bin2hex(client_write->IV.data, client_write->IV.size, buf, sizeof(buf), NULL)); _gnutls_hard_log("INT: SERVER WRITE IV [%d]: %s\n", server_write->IV.size, _gnutls_bin2hex(server_write->IV.data, server_write->IV.size, buf, sizeof(buf), NULL)); } return 0; }
int _gnutls_recv_server_certificate_status(gnutls_session_t session) { uint8_t *data; int data_size; size_t r_size; gnutls_buffer_st buf; int ret; status_request_ext_st *priv = NULL; extension_priv_data_t epriv; ret = _gnutls_ext_get_session_data(session, GNUTLS_EXTENSION_STATUS_REQUEST, &epriv); if (ret < 0) return 0; priv = epriv.ptr; if (!priv->expect_cstatus) return 0; ret = _gnutls_recv_handshake(session, GNUTLS_HANDSHAKE_CERTIFICATE_STATUS, 0, &buf); if (ret < 0) return gnutls_assert_val_fatal(ret); priv->expect_cstatus = 0; data = buf.data; data_size = buf.length; /* minimum message is type (1) + response (3) + data */ if (data_size == 0) return 0; else if (data_size < 4) return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH); if (data[0] != 0x01) { gnutls_assert(); _gnutls_handshake_log("EXT[%p]: unknown status_type %d\n", session, data[0]); return 0; } DECR_LENGTH_COM(data_size, 1, ret = GNUTLS_E_UNEXPECTED_PACKET_LENGTH; goto error); data++; DECR_LENGTH_COM(data_size, 3, ret = GNUTLS_E_UNEXPECTED_PACKET_LENGTH; goto error); r_size = _gnutls_read_uint24(data); data += 3; DECR_LENGTH_COM(data_size, r_size, ret = GNUTLS_E_UNEXPECTED_PACKET_LENGTH; goto error); ret = _gnutls_set_datum(&priv->response, data, r_size); if (ret < 0) goto error; ret = 0; error: _gnutls_buffer_clear(&buf); return ret; }
/* Generates the PSK client key exchange * * * struct { * select (KeyExchangeAlgorithm) { * opaque psk_identity<0..2^16-1>; * } exchange_keys; * } ClientKeyExchange; * */ int _gnutls_gen_psk_client_kx (gnutls_session_t session, opaque ** data) { int ret; gnutls_psk_client_credentials_t cred; cred = (gnutls_psk_client_credentials_t) _gnutls_get_cred (session->key, GNUTLS_CRD_PSK, NULL); if (cred == NULL) { gnutls_assert (); return GNUTLS_E_INSUFFICIENT_CREDENTIALS; } if (cred->username.data == NULL && cred->key.data == NULL && cred->get_function != NULL) { char *username; gnutls_datum_t key; ret = cred->get_function (session, &username, &key); if (ret) { gnutls_assert (); return ret; } ret = _gnutls_set_datum (&cred->username, username, strlen (username)); gnutls_free (username); if (ret < 0) { gnutls_assert (); _gnutls_free_datum (&key); return ret; } ret = _gnutls_set_datum (&cred->key, key.data, key.size); _gnutls_free_datum (&key); if (ret < 0) { gnutls_assert (); return GNUTLS_E_MEMORY_ERROR; } } else if (cred->username.data == NULL || cred->key.data == NULL) { gnutls_assert (); return GNUTLS_E_INSUFFICIENT_CREDENTIALS; } ret = _gnutls_set_psk_session_key (session, NULL); if (ret < 0) { gnutls_assert (); return ret; } (*data) = gnutls_malloc (2 + cred->username.size); if ((*data) == NULL) { gnutls_assert (); return GNUTLS_E_MEMORY_ERROR; } _gnutls_write_datum16 (*data, cred->username); return (cred->username.size + 2); }
/* Upack certificate info. */ static int unpack_certificate_auth_info (gnutls_session_t session, const gnutls_datum_t * packed_session) { int pos = 0, size, ret; unsigned int i = 0, j; size_t pack_size; cert_auth_info_t info; if (packed_session->data[0] != GNUTLS_CRD_CERTIFICATE) { gnutls_assert (); return GNUTLS_E_INVALID_REQUEST; } pack_size = _gnutls_read_uint32 (&packed_session->data[PACK_HEADER_SIZE]); pos += PACK_HEADER_SIZE + 4; if (pack_size == 0) return 0; /* nothing to be done */ /* a simple check for integrity */ if (pack_size + PACK_HEADER_SIZE + 4 > packed_session->size) { gnutls_assert (); return GNUTLS_E_INVALID_REQUEST; } /* client and server have the same auth_info here */ ret = _gnutls_auth_info_set (session, GNUTLS_CRD_CERTIFICATE, sizeof (cert_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; } info->dh.secret_bits = _gnutls_read_uint16 (&packed_session->data[pos]); pos += 2; size = _gnutls_read_uint32 (&packed_session->data[pos]); pos += 4; ret = _gnutls_set_datum (&info->dh.prime, &packed_session->data[pos], size); if (ret < 0) { gnutls_assert (); goto error; } pos += size; size = _gnutls_read_uint32 (&packed_session->data[pos]); pos += 4; ret = _gnutls_set_datum (&info->dh.generator, &packed_session->data[pos], size); if (ret < 0) { gnutls_assert (); goto error; } pos += size; size = _gnutls_read_uint32 (&packed_session->data[pos]); pos += 4; ret = _gnutls_set_datum (&info->dh.public_key, &packed_session->data[pos], size); if (ret < 0) { gnutls_assert (); goto error; } pos += size; size = _gnutls_read_uint32 (&packed_session->data[pos]); pos += 4; ret = _gnutls_set_datum (&info->rsa_export.modulus, &packed_session->data[pos], size); if (ret < 0) { gnutls_assert (); goto error; } pos += size; size = _gnutls_read_uint32 (&packed_session->data[pos]); pos += 4; ret = _gnutls_set_datum (&info->rsa_export.exponent, &packed_session->data[pos], size); if (ret < 0) { gnutls_assert (); goto error; } pos += size; info->ncerts = _gnutls_read_uint32 (&packed_session->data[pos]); pos += 4; if (info->ncerts > 0) { info->raw_certificate_list = gnutls_calloc (1, sizeof (gnutls_datum_t) * info->ncerts); if (info->raw_certificate_list == NULL) { gnutls_assert (); ret = GNUTLS_E_MEMORY_ERROR; goto error; } } for (i = 0; i < info->ncerts; i++) { size = _gnutls_read_uint32 (&packed_session->data[pos]); pos += sizeof (uint32_t); ret = _gnutls_set_datum (&info->raw_certificate_list[i], &packed_session->data[pos], size); pos += size; if (ret < 0) { gnutls_assert (); goto error; } } return 0; error: _gnutls_free_datum (&info->dh.prime); _gnutls_free_datum (&info->dh.generator); _gnutls_free_datum (&info->dh.public_key); _gnutls_free_datum (&info->rsa_export.modulus); _gnutls_free_datum (&info->rsa_export.exponent); for (j = 0; j < i; j++) _gnutls_free_datum (&info->raw_certificate_list[j]); gnutls_free (info->raw_certificate_list); return ret; }