/* Reads an uint32 number from the buffer. If check is non zero it will also check whether * the number read, is less than the data in the buffer */ int _gnutls_buffer_pop_prefix (gnutls_buffer_st * buf, size_t * data_size, int check) { size_t size; if (buf->length < 4) { gnutls_assert (); return GNUTLS_E_PARSING_ERROR; } size = _gnutls_read_uint32 (buf->data); if (check && size > buf->length - 4) { gnutls_assert (); return GNUTLS_E_PARSING_ERROR; } buf->data += 4; buf->length -= 4; *data_size = size; return 0; }
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; }
/** * gnutls_db_check_entry_time: * @entry: is a pointer to a #gnutls_datum_t structure. * @t: is the time of the session handshake * * This function returns the time that this entry was active. * It can be used for database entry expiration. * * Returns: The time this entry was created, or zero on error. **/ time_t gnutls_db_check_entry_time(gnutls_datum_t * entry) { uint32_t t; uint32_t magic; if (entry->size < 8) return gnutls_assert_val(0); magic = _gnutls_read_uint32(entry->data); if (magic != PACKED_SESSION_MAGIC) return gnutls_assert_val(0); t = _gnutls_read_uint32(&entry->data[4]); return t; }
/** * gnutls_openpgp_keyring_check_id: * @ring: holds the keyring to check against * @keyid: will hold the keyid to check for. * @flags: unused (should be 0) * * Check if a given key ID exists in the keyring. * * Returns: %GNUTLS_E_SUCCESS on success (if keyid exists) and a * negative error code on failure. **/ int gnutls_openpgp_keyring_check_id(gnutls_openpgp_keyring_t ring, const gnutls_openpgp_keyid_t keyid, unsigned int flags) { cdk_pkt_pubkey_t pk; uint32_t id[2]; id[0] = _gnutls_read_uint32(keyid); id[1] = _gnutls_read_uint32(&keyid[4]); if (!cdk_keydb_get_pk(ring->db, id, &pk)) { cdk_pk_release(pk); return 0; } _gnutls_debug_log("PGP: key not found %08lX\n", (unsigned long) id[1]); return GNUTLS_E_NO_CERTIFICATE_FOUND; }
static int parse_nst_extension(void *ctx, unsigned tls_id, const unsigned char *data, unsigned data_size) { gnutls_session_t session = ctx; if (tls_id == ext_mod_early_data.tls_id) { if (data_size < 4) return gnutls_assert_val(GNUTLS_E_TLS_PACKET_DECODING_ERROR); session->security_parameters.max_early_data_size = _gnutls_read_uint32(data); } return 0; }
/* this function reads a (small) unsigned integer * from asn1 structs. Combines the read and the convertion * steps. */ int _gnutls_x509_read_uint (ASN1_TYPE node, const char *value, unsigned int *ret) { int len, result; opaque *tmpstr; len = 0; result = asn1_read_value (node, value, NULL, &len); if (result != ASN1_MEM_ERROR) { gnutls_assert (); return _gnutls_asn2err (result); } tmpstr = gnutls_malloc (len); if (tmpstr == NULL) { gnutls_assert (); return GNUTLS_E_MEMORY_ERROR; } result = asn1_read_value (node, value, tmpstr, &len); if (result != ASN1_SUCCESS) { gnutls_assert (); gnutls_free (tmpstr); return _gnutls_asn2err (result); } if (len == 1) *ret = tmpstr[0]; else if (len == 2) *ret = _gnutls_read_uint16 (tmpstr); else if (len == 3) *ret = _gnutls_read_uint24 (tmpstr); else if (len == 4) *ret = _gnutls_read_uint32 (tmpstr); else { gnutls_assert (); gnutls_free (tmpstr); return GNUTLS_E_INTERNAL_ERROR; } gnutls_free (tmpstr); return 0; }
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; }
/* 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; }
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; }
/* 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; }
static int unpack_security_parameters (gnutls_session_t session, const gnutls_datum_t * packed_session) { size_t pack_size, init, i; int pos = 0, len; time_t timestamp = time (0); /* skip the auth info stuff */ init = _gnutls_read_uint32 (&packed_session->data[PACK_HEADER_SIZE]) + 4 + PACK_HEADER_SIZE; pos = init; pack_size = _gnutls_read_uint32 (&packed_session->data[pos]); pos += 4; if (pack_size == 0) return GNUTLS_E_INVALID_REQUEST; /* a simple check for integrity */ if (pack_size > MAX_SEC_PARAMS) { gnutls_assert (); return GNUTLS_E_INVALID_REQUEST; } session->internals.resumed_security_parameters.entity = packed_session->data[pos++]; session->internals.resumed_security_parameters.kx_algorithm = packed_session->data[pos++]; session->internals.resumed_security_parameters.read_bulk_cipher_algorithm = packed_session->data[pos++]; session->internals.resumed_security_parameters.read_mac_algorithm = packed_session->data[pos++]; session->internals.resumed_security_parameters.read_compression_algorithm = packed_session->data[pos++]; session->internals.resumed_security_parameters.write_bulk_cipher_algorithm = packed_session->data[pos++]; session->internals.resumed_security_parameters.write_mac_algorithm = packed_session->data[pos++]; session->internals.resumed_security_parameters.write_compression_algorithm = packed_session->data[pos++]; session->internals.resumed_security_parameters.current_cipher_suite. suite[0] = packed_session->data[pos++]; session->internals.resumed_security_parameters.current_cipher_suite. suite[1] = packed_session->data[pos++]; session->internals.resumed_security_parameters.cert_type = packed_session->data[pos++]; session->internals.resumed_security_parameters.version = packed_session->data[pos++]; memcpy (session->internals.resumed_security_parameters.master_secret, &packed_session->data[pos], TLS_MASTER_SIZE); pos += TLS_MASTER_SIZE; memcpy (session->internals.resumed_security_parameters.client_random, &packed_session->data[pos], TLS_RANDOM_SIZE); pos += TLS_RANDOM_SIZE; memcpy (session->internals.resumed_security_parameters.server_random, &packed_session->data[pos], TLS_RANDOM_SIZE); pos += TLS_RANDOM_SIZE; session->internals.resumed_security_parameters.session_id_size = packed_session->data[pos++]; memcpy (session->internals.resumed_security_parameters.session_id, &packed_session->data[pos], session->internals.resumed_security_parameters.session_id_size); pos += session->internals.resumed_security_parameters.session_id_size; session->internals.resumed_security_parameters.timestamp = _gnutls_read_uint32 (&packed_session->data[pos]); pos += 4; if (timestamp - session->internals.resumed_security_parameters.timestamp > session->internals.expire_time || session->internals.resumed_security_parameters.timestamp > timestamp) { gnutls_assert (); return GNUTLS_E_EXPIRED; } /* Extensions */ session->internals.resumed_security_parameters.max_record_send_size = _gnutls_read_uint16 (&packed_session->data[pos]); pos += 2; session->internals.resumed_security_parameters.max_record_recv_size = _gnutls_read_uint16 (&packed_session->data[pos]); pos += 2; /* SRP */ len = packed_session->data[pos++]; /* srp username length */ memcpy (session->internals.resumed_security_parameters.extensions. srp_username, &packed_session->data[pos], len); session->internals.resumed_security_parameters.extensions. srp_username[len] = 0; pos += len; session->internals.resumed_security_parameters.extensions. server_names_size = _gnutls_read_uint16 (&packed_session->data[pos]); pos += 2; for (i = 0; i < session->internals.resumed_security_parameters.extensions. server_names_size; i++) { session->internals.resumed_security_parameters.extensions. server_names[i].type = packed_session->data[pos++]; session->internals.resumed_security_parameters.extensions. server_names[i].name_length = _gnutls_read_uint16 (&packed_session->data[pos]); pos += 2; memcpy (session->internals.resumed_security_parameters.extensions. server_names[i].name, &packed_session->data[pos], session->internals.resumed_security_parameters.extensions. server_names[i].name_length); pos += session->internals.resumed_security_parameters.extensions. server_names[i].name_length; } return 0; }
static int unpack_ticket(gnutls_session_t session, gnutls_datum_t *packed, tls13_ticket_st *data) { uint32_t age_add, lifetime; struct timespec creation_time; uint8_t resumption_master_secret[MAX_HASH_SIZE]; size_t resumption_master_secret_size; uint8_t nonce[UINT8_MAX]; size_t nonce_size; gnutls_datum_t state; gnutls_mac_algorithm_t kdf; const mac_entry_st *prf; uint8_t *p; ssize_t len; uint64_t v; int ret; if (unlikely(packed == NULL || data == NULL)) return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); memset(data, 0, sizeof(*data)); p = packed->data; len = packed->size; DECR_LEN(len, 2); kdf = _gnutls_read_uint16(p); p += 2; /* Check if the MAC ID we got is valid */ prf = _gnutls_mac_to_entry(kdf); if (prf == NULL) return gnutls_assert_val(GNUTLS_E_ILLEGAL_PARAMETER); /* Read the ticket age add and the ticket lifetime */ DECR_LEN(len, 4); age_add = _gnutls_read_uint32(p); p += 4; DECR_LEN(len, 4); lifetime = _gnutls_read_uint32(p); p += 4; /* * Check if the whole ticket is large enough, * and read the resumption master secret */ DECR_LEN(len, 1); resumption_master_secret_size = *p; p += 1; /* Check if the size of resumption_master_secret matches the PRF */ if (resumption_master_secret_size != prf->output_size) return gnutls_assert_val(GNUTLS_E_ILLEGAL_PARAMETER); DECR_LEN(len, resumption_master_secret_size); memcpy(resumption_master_secret, p, resumption_master_secret_size); p += resumption_master_secret_size; /* Read the ticket nonce */ DECR_LEN(len, 1); nonce_size = *p; p += 1; DECR_LEN(len, nonce_size); memcpy(nonce, p, nonce_size); p += nonce_size; DECR_LEN(len, 2); state.size = _gnutls_read_uint16(p); p += 2; DECR_LEN(len, state.size); state.data = p; p += state.size; DECR_LEN(len, 12); v = _gnutls_read_uint32(p); p += 4; creation_time.tv_sec = (v << 32) | _gnutls_read_uint32(p); p += 4; creation_time.tv_nsec = _gnutls_read_uint32(p); ret = _gnutls_session_unpack(session, &state); if (ret < 0) return gnutls_assert_val(ret); /* No errors - Now return all the data to the caller */ data->prf = prf; memcpy(data->resumption_master_secret, resumption_master_secret, resumption_master_secret_size); memcpy(data->nonce, nonce, nonce_size); data->nonce_size = nonce_size; data->age_add = age_add; data->lifetime = lifetime; memcpy(&data->creation_time, &creation_time, sizeof(struct timespec)); return 0; }
/*- * gnutls_openpgp_get_key - Retrieve a key from the keyring. * @key: the destination context to save the key. * @keyring: the datum struct that contains all keyring information. * @attr: The attribute (keyid, fingerprint, ...). * @by: What attribute is used. * * This function can be used to retrieve keys by different pattern * from a binary or a file keyring. -*/ int gnutls_openpgp_get_key (gnutls_datum_t * key, gnutls_openpgp_keyring_t keyring, key_attr_t by, opaque * pattern) { cdk_kbnode_t knode = NULL; unsigned long keyid[2]; unsigned char *buf; void *desc; size_t len; int rc = 0; cdk_keydb_search_t st; if (!key || !keyring || by == KEY_ATTR_NONE) { gnutls_assert (); return GNUTLS_E_INVALID_REQUEST; } memset (key, 0, sizeof *key); if (by == KEY_ATTR_SHORT_KEYID) { keyid[0] = _gnutls_read_uint32 (pattern); desc = keyid; } else if (by == KEY_ATTR_KEYID) { keyid[0] = _gnutls_read_uint32 (pattern); keyid[1] = _gnutls_read_uint32 (pattern + 4); desc = keyid; } else desc = pattern; rc = cdk_keydb_search_start (&st, keyring->db, by, desc); if (!rc) rc = cdk_keydb_search (st, keyring->db, &knode); cdk_keydb_search_release (st); if (rc) { rc = _gnutls_map_cdk_rc (rc); goto leave; } if (!cdk_kbnode_find (knode, CDK_PKT_PUBLIC_KEY)) { rc = GNUTLS_E_OPENPGP_GETKEY_FAILED; goto leave; } /* We let the function allocate the buffer to avoid to call the function twice. */ rc = cdk_kbnode_write_to_mem_alloc (knode, &buf, &len); if (!rc) datum_append (key, buf, len); gnutls_free (buf); leave: cdk_kbnode_release (knode); return rc; }