/** * gnutls_openpgp_privkey_get_subkey_id: * @key: the structure that contains the OpenPGP secret key. * @idx: the subkey index * @keyid: the buffer to save the keyid. * * Get the key-id for the subkey. * * Returns: the 64-bit keyID of the OpenPGP key. * * Since: 2.4.0 **/ int gnutls_openpgp_privkey_get_subkey_id(gnutls_openpgp_privkey_t key, unsigned int idx, gnutls_openpgp_keyid_t keyid) { cdk_packet_t pkt; uint32_t kid[2]; if (!key || !keyid) { gnutls_assert(); return GNUTLS_E_INVALID_REQUEST; } if (idx == GNUTLS_OPENPGP_MASTER_KEYID_IDX) return gnutls_openpgp_privkey_get_key_id(key, keyid); pkt = _get_secret_subkey(key, idx); if (!pkt) return GNUTLS_E_OPENPGP_GETKEY_FAILED; cdk_sk_get_keyid(pkt->pkt.secret_key, kid); _gnutls_write_uint32(kid[0], keyid); _gnutls_write_uint32(kid[1], keyid + 4); return 0; }
static int pack_ticket(gnutls_session_t session, tls13_ticket_st *ticket, gnutls_datum_t *packed) { uint8_t *p; gnutls_datum_t state; int ret; ret = _gnutls_session_pack(session, &state); if (ret < 0) return gnutls_assert_val(ret); packed->size = 2 + 4 + 4 + 1 + ticket->prf->output_size + 1 + ticket->nonce_size + 2 + state.size + 12; packed->data = gnutls_malloc(packed->size); if (!packed->data) { gnutls_assert(); ret = GNUTLS_E_MEMORY_ERROR; goto cleanup; } p = packed->data; _gnutls_write_uint16(ticket->prf->id, p); p += 2; _gnutls_write_uint32(ticket->age_add, p); p += 4; _gnutls_write_uint32(ticket->lifetime, p); p += 4; *p = ticket->prf->output_size; p += 1; memcpy(p, ticket->resumption_master_secret, ticket->prf->output_size); p += ticket->prf->output_size; *p = ticket->nonce_size; p += 1; memcpy(p, ticket->nonce, ticket->nonce_size); p += ticket->nonce_size; _gnutls_write_uint16(state.size, p); p += 2; memcpy(p, state.data, state.size); p += state.size; _gnutls_write_uint32((uint64_t) ticket->creation_time.tv_sec >> 32, p); p += 4; _gnutls_write_uint32(ticket->creation_time.tv_sec & 0xFFFFFFFF, p); p += 4; _gnutls_write_uint32(ticket->creation_time.tv_nsec, p); ret = 0; cleanup: gnutls_free(state.data); return ret; }
int _gnutls_buffer_append_prefix (gnutls_buffer_st * buf, int pfx_size, size_t data_size) { opaque ss[4]; if (pfx_size == 32) { _gnutls_write_uint32 (data_size, ss); pfx_size = 4; } else if (pfx_size == 24) { _gnutls_write_uint24 (data_size, ss); pfx_size = 3; } else if (pfx_size == 16) { _gnutls_write_uint16 (data_size, ss); pfx_size = 2; } else if (pfx_size == 8) { ss[0] = data_size; pfx_size = 1; } else return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); return _gnutls_buffer_append_data (buf, ss, pfx_size); }
void _gnutls_write_datum32 (opaque * dest, gnutls_datum_t dat) { _gnutls_write_uint32 (dat.size, dest); if (dat.data != NULL) memcpy (&dest[4], dat.data, dat.size); }
static int aes_gcm_decrypt(void *_ctx, const void *src, size_t src_size, void *dst, size_t dst_size) { struct aes_gcm_ctx *ctx = _ctx; int blocks = src_size / GCM_BLOCK_SIZE; int exp_blocks = blocks * GCM_BLOCK_SIZE; int rest = src_size - (exp_blocks); uint32_t counter; gcm_ghash(ctx, src, src_size); ctx->gcm.len.u[1] += src_size; if (blocks > 0) { ctr32_encrypt_blocks(src, dst, blocks, ALIGN16(&ctx->expanded_key), ctx->gcm.Yi.c); counter = _gnutls_read_uint32(ctx->gcm.Yi.c + 12); counter += blocks; _gnutls_write_uint32(counter, ctx->gcm.Yi.c + 12); } if (rest > 0) /* last incomplete block */ ctr_encrypt_last(ctx, src, dst, exp_blocks, rest); return 0; }
/* 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_buffer_st * ps) { int cur_size, ret; anon_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); } /* write the real size */ _gnutls_write_uint32 (ps->length - cur_size, ps->data + size_offset); return 0; }
int _gnutls_ext_pack(gnutls_session_t session, gnutls_buffer_st * packed) { unsigned int i; int ret; extension_priv_data_t data; int cur_size; int size_offset; int total_exts_pos; int exts = 0; total_exts_pos = packed->length; BUFFER_APPEND_NUM(packed, 0); for (i = 0; i < extfunc_size; i++) { ret = _gnutls_ext_get_session_data(session, extfunc[i].type, &data); if (ret >= 0 && extfunc[i].pack_func != NULL) { BUFFER_APPEND_NUM(packed, extfunc[i].type); size_offset = packed->length; BUFFER_APPEND_NUM(packed, 0); cur_size = packed->length; ret = extfunc[i].pack_func(data, packed); if (ret < 0) { gnutls_assert(); return ret; } exts++; /* write the actual size */ _gnutls_write_uint32(packed->length - cur_size, packed->data + size_offset); } } _gnutls_write_uint32(exts, packed->data + total_exts_pos); return 0; }
/* 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; }
/** * gnutls_openpgp_privkey_get_key_id: * @key: the structure that contains the OpenPGP secret key. * @keyid: the buffer to save the keyid. * * Get key-id. * * Returns: the 64-bit keyID of the OpenPGP key. * * Since: 2.4.0 **/ int gnutls_openpgp_privkey_get_key_id(gnutls_openpgp_privkey_t key, gnutls_openpgp_keyid_t keyid) { cdk_packet_t pkt; uint32_t kid[2]; if (!key || !keyid) { gnutls_assert(); return GNUTLS_E_INVALID_REQUEST; } pkt = cdk_kbnode_find_packet(key->knode, CDK_PKT_SECRET_KEY); if (!pkt) return GNUTLS_E_OPENPGP_GETKEY_FAILED; cdk_sk_get_keyid(pkt->pkt.secret_key, kid); _gnutls_write_uint32(kid[0], keyid); _gnutls_write_uint32(kid[1], keyid + 4); return 0; }
/* Writes the specified integer into the specified node. */ int _gnutls_x509_write_uint32 (ASN1_TYPE node, const char *value, uint32_t num) { opaque tmpstr[4]; int result; _gnutls_write_uint32 (num, tmpstr); result = asn1_write_value (node, value, tmpstr, 4); if (result != ASN1_SUCCESS) { gnutls_assert (); return _gnutls_asn2err (result); } 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 * 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; }
/* 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 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; }
int _gnutls_send_new_session_ticket(gnutls_session_t session, int again) { mbuffer_st *bufel = NULL; uint8_t *data = NULL, *p; int data_size = 0; int ret; struct ticket_st ticket; uint16_t ticket_len; session_ticket_ext_st *priv = NULL; extension_priv_data_t epriv; uint16_t epoch_saved = session->security_parameters.epoch_write; if (again == 0) { ret = _gnutls_ext_get_session_data(session, GNUTLS_EXTENSION_SESSION_TICKET, &epriv); if (ret < 0) return 0; priv = epriv; if (!priv->session_ticket_renew) return 0; /* XXX: Temporarily set write algorithms to be used. _gnutls_write_connection_state_init() does this job, but it also triggers encryption, while NewSessionTicket should not be encrypted in the record layer. */ ret = _gnutls_epoch_set_keys(session, session->security_parameters. epoch_next); if (ret < 0) { gnutls_assert(); return ret; } session->security_parameters.epoch_write = session->security_parameters.epoch_next; ret = encrypt_ticket(session, priv, &ticket); session->security_parameters.epoch_write = epoch_saved; if (ret < 0) { gnutls_assert(); return ret; } ticket_len = KEY_NAME_SIZE + IV_SIZE + 2 + ticket.encrypted_state_len + MAC_SIZE; bufel = _gnutls_handshake_alloc(session, 4 + 2 + ticket_len); if (!bufel) { gnutls_assert(); gnutls_free(ticket.encrypted_state); return GNUTLS_E_MEMORY_ERROR; } data = _mbuffer_get_udata_ptr(bufel); p = data; _gnutls_write_uint32(session->internals.expire_time, p); p += 4; _gnutls_write_uint16(ticket_len, p); p += 2; memcpy(p, ticket.key_name, KEY_NAME_SIZE); p += KEY_NAME_SIZE; memcpy(p, ticket.IV, IV_SIZE); p += IV_SIZE; _gnutls_write_uint16(ticket.encrypted_state_len, p); p += 2; memcpy(p, ticket.encrypted_state, ticket.encrypted_state_len); gnutls_free(ticket.encrypted_state); p += ticket.encrypted_state_len; memcpy(p, ticket.mac, MAC_SIZE); p += MAC_SIZE; data_size = p - data; session->internals.ticket_sent = 1; } return _gnutls_send_handshake(session, data_size ? bufel : NULL, GNUTLS_HANDSHAKE_NEW_SESSION_TICKET); }
/* * Return zero if session tickets haven't been enabled. */ int _gnutls_send_new_session_ticket(gnutls_session_t session, int again) { mbuffer_st *bufel = NULL; uint8_t *data = NULL, *p; int data_size = 0; int ret; gnutls_datum_t state = { NULL, 0 }; uint16_t epoch_saved = session->security_parameters.epoch_write; gnutls_datum_t ticket_data; if (again == 0) { if (session->internals.flags & GNUTLS_NO_TICKETS) return 0; if (!session->internals.session_ticket_renew) return 0; _gnutls_handshake_log ("HSK[%p]: sending session ticket\n", session); /* XXX: Temporarily set write algorithms to be used. _gnutls_write_connection_state_init() does this job, but it also triggers encryption, while NewSessionTicket should not be encrypted in the record layer. */ ret = _gnutls_epoch_set_keys(session, session->security_parameters. epoch_next, 0); if (ret < 0) { gnutls_assert(); return ret; } /* Under TLS1.2 with session tickets, the session ID is used for different * purposes than the TLS1.0 session ID. Ensure that there is an internally * set value which the server will see on the original and resumed sessions */ if (session->internals.resumed != RESUME_TRUE) { ret = _gnutls_generate_session_id(session->security_parameters. session_id, &session->security_parameters. session_id_size); if (ret < 0) { gnutls_assert(); return ret; } } session->security_parameters.epoch_write = session->security_parameters.epoch_next; /* Pack security parameters. */ ret = _gnutls_session_pack(session, &state); if (ret < 0) { gnutls_assert(); return ret; } /* Generate an encrypted ticket */ ret = _gnutls_encrypt_session_ticket(session, &state, &ticket_data); session->security_parameters.epoch_write = epoch_saved; _gnutls_free_datum(&state); if (ret < 0) { gnutls_assert(); return ret; } bufel = _gnutls_handshake_alloc(session, 4 + 2 + ticket_data.size); if (!bufel) { gnutls_assert(); _gnutls_free_datum(&ticket_data); return GNUTLS_E_MEMORY_ERROR; } data = _mbuffer_get_udata_ptr(bufel); p = data; _gnutls_write_uint32(session->internals.expire_time, p); p += 4; _gnutls_write_uint16(ticket_data.size, p); p += 2; memcpy(p, ticket_data.data, ticket_data.size); p += ticket_data.size; _gnutls_free_datum(&ticket_data); data_size = p - data; session->internals.hsk_flags |= HSK_TLS12_TICKET_SENT; } return _gnutls_send_handshake(session, data_size ? bufel : NULL, GNUTLS_HANDSHAKE_NEW_SESSION_TICKET); }
/* 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_datum_t * packed_session) { unsigned int pos = 0, i; int cert_size, pack_size; cert_auth_info_t info = _gnutls_get_auth_info (session); if (info == NULL && session->key->auth_info_size != 0) { gnutls_assert (); return GNUTLS_E_INVALID_REQUEST; } if (info) { cert_size = 4; for (i = 0; i < info->ncerts; i++) cert_size += 4 + info->raw_certificate_list[i].size; pack_size = 2 + 4 + info->dh.prime.size + 4 + info->dh.generator.size + 4 + info->dh.public_key.size + 4 + info->rsa_export.modulus.size + 4 + info->rsa_export.exponent.size + cert_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_CERTIFICATE; _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; _gnutls_write_datum32 (&packed_session->data[pos], info->rsa_export.modulus); pos += 4 + info->rsa_export.modulus.size; _gnutls_write_datum32 (&packed_session->data[pos], info->rsa_export.exponent); pos += 4 + info->rsa_export.exponent.size; _gnutls_write_uint32 (info->ncerts, &packed_session->data[pos]); pos += 4; for (i = 0; i < info->ncerts; i++) { _gnutls_write_datum32 (&packed_session->data[pos], info->raw_certificate_list[i]); pos += sizeof (uint32_t) + info->raw_certificate_list[i].size; } } 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_datum_t * packed_session) { psk_auth_info_t info; int pack_size, username_size = 0, pos; info = _gnutls_get_auth_info (session); if (info == NULL && session->key->auth_info_size != 0) { gnutls_assert (); return GNUTLS_E_INVALID_REQUEST; } if (info) { username_size = strlen (info->username) + 1; /* include the terminating null */ pack_size = username_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; } pos = 0; packed_session->data[pos] = GNUTLS_CRD_PSK; pos++; _gnutls_write_uint32 (pack_size, &packed_session->data[pos]); pos += 4; if (pack_size > 0) { _gnutls_write_uint32 (username_size, &packed_session->data[pos]); pos += 4; memcpy (&packed_session->data[pos], info->username, username_size); pos += username_size; _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; }
/* Format: * 4 bytes the total security data size * 1 byte the entity type (client/server) * 1 byte the key exchange algorithm used * 1 byte the read cipher algorithm * 1 byte the read mac algorithm * 1 byte the read compression algorithm * * 1 byte the write cipher algorithm * 1 byte the write mac algorithm * 1 byte the write compression algorithm * * 1 byte the certificate type * 1 byte the protocol version * * 2 bytes the cipher suite * * 48 bytes the master secret * * 32 bytes the client random * 32 bytes the server random * * 1 byte the session ID size * x bytes the session ID (32 bytes max) * * 4 bytes a timestamp * ------------------- * MAX: 165 bytes * * EXTENSIONS: * 2 bytes the record send size * 2 bytes the record recv size * * 1 byte the SRP username size * x bytes the SRP username (MAX_SRP_USERNAME) * * 2 bytes the number of server name extensions (up to MAX_SERVER_NAME_EXTENSIONS) * 1 byte the first name type * 2 bytes the size of the first name * x bytes the first name (MAX_SERVER_NAME_SIZE) * and so on... * * -------------------- * MAX: 7+MAX_SRP_USERNAME+MAX_SERVER_NAME_EXTENSIONS*(3+MAX_SERVER_NAME_SIZE) */ static int pack_security_parameters (gnutls_session_t session, gnutls_datum_t * packed_session) { int pos = 0; size_t len, init, i; /* move after the auth info stuff. */ init = _gnutls_read_uint32 (&packed_session->data[PACK_HEADER_SIZE]) + 4 + PACK_HEADER_SIZE; pos = init + 4; /* make some space to write later the size */ packed_session->data[pos++] = session->security_parameters.entity; packed_session->data[pos++] = session->security_parameters.kx_algorithm; packed_session->data[pos++] = session->security_parameters.read_bulk_cipher_algorithm; packed_session->data[pos++] = session->security_parameters.read_mac_algorithm; packed_session->data[pos++] = session->security_parameters.read_compression_algorithm; packed_session->data[pos++] = session->security_parameters.write_bulk_cipher_algorithm; packed_session->data[pos++] = session->security_parameters.write_mac_algorithm; packed_session->data[pos++] = session->security_parameters.write_compression_algorithm; packed_session->data[pos++] = session->security_parameters.current_cipher_suite.suite[0]; packed_session->data[pos++] = session->security_parameters.current_cipher_suite.suite[1]; packed_session->data[pos++] = session->security_parameters.cert_type; packed_session->data[pos++] = session->security_parameters.version; memcpy (&packed_session->data[pos], session->security_parameters.master_secret, TLS_MASTER_SIZE); pos += TLS_MASTER_SIZE; memcpy (&packed_session->data[pos], session->security_parameters.client_random, TLS_RANDOM_SIZE); pos += TLS_RANDOM_SIZE; memcpy (&packed_session->data[pos], session->security_parameters.server_random, TLS_RANDOM_SIZE); pos += TLS_RANDOM_SIZE; packed_session->data[pos++] = session->security_parameters.session_id_size; memcpy (&packed_session->data[pos], session->security_parameters.session_id, session->security_parameters.session_id_size); pos += session->security_parameters.session_id_size; _gnutls_write_uint32 (session->security_parameters.timestamp, &packed_session->data[pos]); pos += 4; /* Extensions */ _gnutls_write_uint16 (session->security_parameters.max_record_send_size, &packed_session->data[pos]); pos += 2; _gnutls_write_uint16 (session->security_parameters.max_record_recv_size, &packed_session->data[pos]); pos += 2; /* SRP */ len = strlen ((char *) session->security_parameters.extensions.srp_username); packed_session->data[pos++] = len; memcpy (&packed_session->data[pos], session->security_parameters.extensions.srp_username, len); pos += len; _gnutls_write_uint16 (session->security_parameters.extensions. server_names_size, &packed_session->data[pos]); pos += 2; for (i = 0; i < session->security_parameters.extensions.server_names_size; i++) { packed_session->data[pos++] = session->security_parameters.extensions.server_names[i].type; _gnutls_write_uint16 (session->security_parameters.extensions. server_names[i].name_length, &packed_session->data[pos]); pos += 2; memcpy (&packed_session->data[pos], session->security_parameters.extensions.server_names[i].name, session->security_parameters.extensions.server_names[i]. name_length); pos += session->security_parameters.extensions.server_names[i].name_length; } /* write the total size */ _gnutls_write_uint32 (pos - init - 4, &packed_session->data[init]); packed_session->size += pos - init; return 0; }
/* Format: * 4 bytes the total security data size * 1 byte the entity type (client/server) * 1 byte the key exchange algorithm used * 1 byte the read cipher algorithm * 1 byte the read mac algorithm * 1 byte the read compression algorithm * * 1 byte the write cipher algorithm * 1 byte the write mac algorithm * 1 byte the write compression algorithm * * 1 byte the certificate type * 1 byte the protocol version * * 2 bytes the cipher suite * * 48 bytes the master secret * * 32 bytes the client random * 32 bytes the server random * * 1 byte the session ID size * x bytes the session ID (32 bytes max) * * 4 bytes a timestamp * ------------------- * MAX: 165 bytes * */ static int pack_security_parameters (gnutls_session_t session, gnutls_buffer_st * ps) { int ret; int size_offset; size_t cur_size; record_parameters_st *params; if (session->security_parameters.epoch_read != session->security_parameters.epoch_write) { gnutls_assert (); return GNUTLS_E_INVALID_REQUEST; } ret = _gnutls_epoch_get (session, EPOCH_READ_CURRENT, ¶ms); if (ret < 0) { gnutls_assert (); return ret; } /* move after the auth info stuff. */ size_offset = ps->length; BUFFER_APPEND_NUM (ps, 0); cur_size = ps->length; BUFFER_APPEND (ps, &session->security_parameters.entity, 1); BUFFER_APPEND (ps, &session->security_parameters.kx_algorithm, 1); BUFFER_APPEND (ps, &session->security_parameters.current_cipher_suite.suite[0], 1); BUFFER_APPEND (ps, &session->security_parameters.current_cipher_suite.suite[1], 1); BUFFER_APPEND (ps, ¶ms->compression_algorithm, 1); BUFFER_APPEND (ps, &session->security_parameters.cert_type, 1); BUFFER_APPEND (ps, &session->security_parameters.version, 1); BUFFER_APPEND (ps, session->security_parameters.master_secret, GNUTLS_MASTER_SIZE); BUFFER_APPEND (ps, session->security_parameters.client_random, GNUTLS_RANDOM_SIZE); BUFFER_APPEND (ps, session->security_parameters.server_random, GNUTLS_RANDOM_SIZE); BUFFER_APPEND_NUM (ps, session->security_parameters.session_id_size); BUFFER_APPEND (ps, session->security_parameters.session_id, session->security_parameters.session_id_size); BUFFER_APPEND_NUM (ps, session->security_parameters.max_record_send_size); BUFFER_APPEND_NUM (ps, session->security_parameters.max_record_recv_size); BUFFER_APPEND_NUM (ps, session->security_parameters.timestamp); _gnutls_write_uint32 (ps->length - cur_size, ps->data + size_offset); return 0; }