/** * gnutls_x509_privkey_export_ecc_raw: * @key: a structure that holds the rsa parameters * @curve: will hold the curve * @x: will hold the x coordinate * @y: will hold the y coordinate * @k: will hold the private key * * This function will export the ECC private key's parameters found * in the given structure. The new parameters will be allocated using * gnutls_malloc() and will be stored in the appropriate datum. * * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a * negative error value. * * Since: 3.0 **/ int gnutls_x509_privkey_export_ecc_raw (gnutls_x509_privkey_t key, gnutls_ecc_curve_t *curve, gnutls_datum_t * x, gnutls_datum_t * y, gnutls_datum_t* k) { int ret; if (key == NULL) { gnutls_assert (); return GNUTLS_E_INVALID_REQUEST; } *curve = key->params.flags; /* X */ ret = _gnutls_mpi_dprint_lz (key->params.params[ECC_X], x); if (ret < 0) { gnutls_assert (); return ret; } /* Y */ ret = _gnutls_mpi_dprint_lz (key->params.params[ECC_Y], y); if (ret < 0) { gnutls_assert (); _gnutls_free_datum (x); return ret; } /* K */ ret = _gnutls_mpi_dprint_lz (key->params.params[ECC_K], k); if (ret < 0) { gnutls_assert (); _gnutls_free_datum (x); _gnutls_free_datum (y); return ret; } return 0; }
/** * gnutls_x509_trust_list_add_crls: * @list: The structure of the list * @crl_list: A list of CRLs * @crl_size: The length of the CRL list * @flags: if GNUTLS_TL_VERIFY_CRL is given the CRLs will be verified before being added. * @verification_flags: gnutls_certificate_verify_flags if flags specifies GNUTLS_TL_VERIFY_CRL * * This function will add the given certificate revocation lists * to the trusted list. The list of CRLs must not be deinitialized * during this structure's lifetime. * * This function must be called after gnutls_x509_trust_list_add_cas() * to allow verifying the CRLs for validity. * * Returns: The number of added elements is returned. * * Since: 3.0.0 **/ int gnutls_x509_trust_list_add_crls(gnutls_x509_trust_list_t list, const gnutls_x509_crl_t * crl_list, int crl_size, unsigned int flags, unsigned int verification_flags) { int ret, i, j = 0; gnutls_datum_t dn; unsigned int vret = 0; uint32_t hash; /* Probably we can optimize things such as removing duplicates * etc. */ if (crl_size == 0 || crl_list == NULL) return 0; for (i = 0; i < crl_size; i++) { ret = gnutls_x509_crl_get_raw_issuer_dn(crl_list[i], &dn); if (ret < 0) { gnutls_assert(); return i; } hash = _gnutls_bhash(dn.data, dn.size, INIT_HASH); hash %= list->size; _gnutls_free_datum(&dn); if (flags & GNUTLS_TL_VERIFY_CRL) { ret = gnutls_x509_crl_verify(crl_list[i], list->node[hash].trusted_cas, list->node[hash].trusted_ca_size, verification_flags, &vret); if (ret < 0 || vret != 0) continue; } list->node[hash].crls = gnutls_realloc_fast(list->node[hash].crls, (list->node[hash].crl_size + 1) * sizeof(list->node[hash].trusted_cas[0])); if (list->node[hash].crls == NULL) { gnutls_assert(); return i; } list->node[hash].crls[list->node[hash].crl_size] = crl_list[i]; list->node[hash].crl_size++; j++; } return j; }
/** * gnutls_pkcs7_get_crl_raw: * @pkcs7: should contain a #gnutls_pkcs7_t structure * @indx: contains the index of the crl to extract * @crl: the contents of the crl will be copied there (may be null) * @crl_size: should hold the size of the crl * * This function will return a crl of the PKCS7 or RFC2630 crl set. * * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a * negative error value. If the provided buffer is not long enough, * then @crl_size is updated and %GNUTLS_E_SHORT_MEMORY_BUFFER is * returned. After the last crl has been read * %GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE will be returned. **/ int gnutls_pkcs7_get_crl_raw(gnutls_pkcs7_t pkcs7, int indx, void *crl, size_t * crl_size) { ASN1_TYPE c2 = ASN1_TYPE_EMPTY; int result; char root2[ASN1_MAX_NAME_SIZE]; gnutls_datum_t tmp = { NULL, 0 }; int start, end; if (pkcs7 == NULL || crl_size == NULL) return GNUTLS_E_INVALID_REQUEST; /* Step 1. decode the signed data. */ result = _decode_pkcs7_signed_data(pkcs7->pkcs7, &c2, &tmp); if (result < 0) { gnutls_assert(); return result; } /* Step 2. Parse the CertificateSet */ snprintf(root2, sizeof(root2), "crls.?%u", indx + 1); /* Get the raw CRL */ result = asn1_der_decoding_startEnd(c2, tmp.data, tmp.size, root2, &start, &end); if (result != ASN1_SUCCESS) { gnutls_assert(); result = _gnutls_asn2err(result); goto cleanup; } end = end - start + 1; if ((unsigned) end > *crl_size) { *crl_size = end; result = GNUTLS_E_SHORT_MEMORY_BUFFER; goto cleanup; } if (crl) memcpy(crl, &tmp.data[start], end); *crl_size = end; result = 0; cleanup: _gnutls_free_datum(&tmp); if (c2) asn1_delete_structure(&c2); return result; }
/* This function will convert an attribute value, specified by the OID, * to a string. The result will be a null terminated string. * * res may be null. This will just return the res_size, needed to * hold the string. */ int _gnutls_x509_dn_to_string(const char *oid, void *value, int value_size, gnutls_datum_t * str) { const struct oid_to_string *oentry; int ret; gnutls_datum_t tmp; size_t size; if (value == NULL || value_size <= 0) { gnutls_assert(); return GNUTLS_E_INVALID_REQUEST; } oentry = get_oid_entry(oid); if (oentry == NULL) { /* unknown OID -> hex */ unknown_oid: str->size = value_size * 2 + 2; str->data = gnutls_malloc(str->size); if (str->data == NULL) return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); size = str->size; ret = data2hex(value, value_size, str->data, &size); if (ret < 0) { gnutls_assert(); gnutls_free(str->data); return ret; } str->size = size; return 0; } if (oentry->asn_desc != NULL) { /* complex */ ret = decode_complex_string(oentry, value, value_size, &tmp); if (ret < 0) { /* we failed decoding -> handle it as unknown OID */ goto unknown_oid; } } else { ret = _gnutls_x509_decode_string(oentry->etype, value, value_size, &tmp); if (ret < 0) { /* we failed decoding -> handle it as unknown OID */ goto unknown_oid; } } ret = str_escape(&tmp, str); _gnutls_free_datum(&tmp); if (ret < 0) return gnutls_assert_val(ret); return 0; }
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; }
/* Takes a certificate list and shortens it if there are * intermedia certificates already trusted by us. * * FIXME: This is very similar to _gnutls_x509_verify_certificate(). * * Returns the new size of the list or a negative number on error. */ static int shorten_clist(gnutls_x509_trust_list_t list, gnutls_x509_crt_t * certificate_list, int clist_size) { int i, ret; uint32_t hash; gnutls_datum_t dn; if (clist_size > 1) { /* Check if the last certificate in the path is self signed. * In that case ignore it (a certificate is trusted only if it * leads to a trusted party by us, not the server's). * * This prevents from verifying self signed certificates against * themselves. This (although not bad) caused verification * failures on some root self signed certificates that use the * MD2 algorithm. */ if (gnutls_x509_crt_check_issuer(certificate_list[clist_size - 1], certificate_list[clist_size - 1]) > 0) { clist_size--; } } /* We want to shorten the chain by removing the cert that matches * one of the certs we trust and all the certs after that i.e. if * cert chain is A signed-by B signed-by C signed-by D (signed-by * self-signed E but already removed above), and we trust B, remove * B, C and D. */ for (i = 1; i < clist_size; i++) { int j; ret = gnutls_x509_crt_get_raw_issuer_dn(certificate_list[i], &dn); if (ret < 0) { gnutls_assert(); return ret; } hash = _gnutls_bhash(dn.data, dn.size, INIT_HASH); hash %= list->size; _gnutls_free_datum(&dn); for (j = 0; j < list->node[hash].trusted_ca_size; j++) { if (check_if_same_cert (certificate_list[i], list->node[hash].trusted_cas[j]) == 0) { /* cut the list at the point of first the trusted certificate */ clist_size = i + 1; break; } } /* clist_size may have been changed which gets out of loop */ } return clist_size; }
/** * gnutls_pkcs12_bag_decrypt - This function will decrypt an encrypted bag * @bag: The bag * @pass: The password used for encryption. This can only be ASCII. * * This function will decrypt the given encrypted bag and return 0 on success. * **/ int gnutls_pkcs12_bag_decrypt (gnutls_pkcs12_bag_t bag, const char *pass) { int ret; gnutls_datum_t dec; if (bag == NULL) { gnutls_assert (); return GNUTLS_E_INVALID_REQUEST; } if (bag->element[0].type != GNUTLS_BAG_ENCRYPTED) { gnutls_assert (); return GNUTLS_E_INVALID_REQUEST; } ret = _gnutls_pkcs7_decrypt_data (&bag->element[0].data, pass, &dec); if (ret < 0) { gnutls_assert (); return ret; } /* decryption succeeded. Now decode the SafeContents * stuff, and parse it. */ _gnutls_free_datum (&bag->element[0].data); ret = _pkcs12_decode_safe_contents (&dec, bag); _gnutls_free_datum (&dec); if (ret < 0) { gnutls_assert (); return ret; } return 0; }
static int _get_authority_key_id(gnutls_x509_crl_t cert, ASN1_TYPE * c2, unsigned int *critical) { int ret; gnutls_datum_t id; *c2 = ASN1_TYPE_EMPTY; if (cert == NULL) { gnutls_assert(); return GNUTLS_E_INVALID_REQUEST; } if ((ret = _gnutls_x509_crl_get_extension(cert, "2.5.29.35", 0, &id, critical)) < 0) { return gnutls_assert_val(ret); } if (id.size == 0 || id.data == NULL) { gnutls_assert(); return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; } ret = asn1_create_element (_gnutls_get_pkix(), "PKIX1.AuthorityKeyIdentifier", c2); if (ret != ASN1_SUCCESS) { gnutls_assert(); _gnutls_free_datum(&id); return _gnutls_asn2err(ret); } ret = asn1_der_decoding(c2, id.data, id.size, NULL); _gnutls_free_datum(&id); if (ret != ASN1_SUCCESS) { gnutls_assert(); asn1_delete_structure(c2); return _gnutls_asn2err(ret); } return 0; }
/** * 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_x509_trust_list_verify_named_crt: * @list: The structure of the list * @cert: is the certificate to be verified * @name: is the certificate's name * @name_size: is the certificate's name size * @flags: Flags that may be used to change the verification algorithm. Use OR of the gnutls_certificate_verify_flags enumerations. * @verify: will hold the certificate verification output. * @func: If non-null will be called on each chain element verification with the output. * * This function will try to find a matching named certificate. If a * match is found the certificate is considered valid. In addition to that * this function will also check CRLs. * * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a * negative error value. * * Since: 3.0 **/ int gnutls_x509_trust_list_verify_named_crt(gnutls_x509_trust_list_t list, gnutls_x509_crt_t cert, const void *name, size_t name_size, unsigned int flags, unsigned int *verify, gnutls_verify_output_function func) { gnutls_datum_t dn; int ret; unsigned int i; uint32_t hash; ret = gnutls_x509_crt_get_raw_issuer_dn(cert, &dn); if (ret < 0) { gnutls_assert(); return ret; } hash = _gnutls_bhash(dn.data, dn.size, INIT_HASH); hash %= list->size; _gnutls_free_datum(&dn); *verify = GNUTLS_CERT_INVALID; for (i = 0; i < list->node[hash].named_cert_size; i++) { if (check_if_same_cert(cert, list->node[hash].named_certs[i].cert) == 0) { /* check if name matches */ if (list->node[hash].named_certs[i].name_size == name_size && memcmp(list->node[hash].named_certs[i].name, name, name_size) == 0) { *verify = 0; break; } } } if (*verify != 0 || (flags & GNUTLS_VERIFY_DISABLE_CRL_CHECKS)) return 0; /* Check revocation of individual certificates. * start with the last one that we already have its hash */ ret = _gnutls_x509_crt_check_revocation(cert, list->node[hash].crls, list->node[hash].crl_size, func); if (ret == 1) { /* revoked */ *verify |= GNUTLS_CERT_REVOKED; *verify |= GNUTLS_CERT_INVALID; return 0; } return 0; }
/* If the psk flag is set, then an empty psk_identity_hint will * be inserted */ int _gnutls_ecdh_common_print_server_kx(gnutls_session_t session, gnutls_buffer_st * data, gnutls_ecc_curve_t curve) { uint8_t p; int ret; gnutls_datum_t out; if (curve == GNUTLS_ECC_CURVE_INVALID) return gnutls_assert_val(GNUTLS_E_ECC_NO_SUPPORTED_CURVES); /* just in case we are resuming a session */ gnutls_pk_params_release(&session->key.ecdh_params); gnutls_pk_params_init(&session->key.ecdh_params); /* curve type */ p = 3; ret = _gnutls_buffer_append_data(data, &p, 1); if (ret < 0) return gnutls_assert_val(ret); ret = _gnutls_buffer_append_prefix(data, 16, _gnutls_ecc_curve_get_tls_id (curve)); if (ret < 0) return gnutls_assert_val(ret); /* generate temporal key */ ret = _gnutls_pk_generate_keys(GNUTLS_PK_EC, curve, &session->key.ecdh_params); if (ret < 0) return gnutls_assert_val(ret); ret = _gnutls_ecc_ansi_x963_export(curve, session->key.ecdh_params. params[ECC_X] /* x */ , session->key.ecdh_params. params[ECC_Y] /* y */ , &out); if (ret < 0) return gnutls_assert_val(ret); ret = _gnutls_buffer_append_data_prefix(data, 8, out.data, out.size); _gnutls_free_datum(&out); if (ret < 0) return gnutls_assert_val(ret); return data->length; }
static int gen_ecdhe_psk_client_kx(gnutls_session_t session, gnutls_buffer_st * data) { int ret, free; gnutls_psk_client_credentials_t cred; gnutls_datum_t username, key; cred = (gnutls_psk_client_credentials_t) _gnutls_get_cred(session, GNUTLS_CRD_PSK, NULL); if (cred == NULL) return gnutls_assert_val(GNUTLS_E_INSUFFICIENT_CREDENTIALS); ret = _gnutls_find_psk_key(session, cred, &username, &key, &free); if (ret < 0) return gnutls_assert_val(ret); ret = _gnutls_buffer_append_data_prefix(data, 16, username.data, username.size); if (ret < 0) { gnutls_assert(); goto cleanup; } /* The PSK key is set in there */ ret = _gnutls_gen_ecdh_common_client_kx_int(session, data, &key); if (ret < 0) { gnutls_assert(); goto cleanup; } ret = data->length; cleanup: if (free) { _gnutls_free_datum(&username); _gnutls_free_datum(&key); } return ret; }
/* if hash==MD5 then we do RSA-MD5 * if hash==SHA then we do RSA-SHA * params[0] is modulus * params[1] is public key */ static int pkcs1_rsa_sign (gnutls_digest_algorithm_t hash, const gnutls_datum_t * text, bigint_t * params, int params_len, gnutls_datum_t * signature) { int ret; opaque _digest[MAX_HASH_SIZE]; digest_hd_st hd; gnutls_datum_t digest, info; ret = _gnutls_hash_init (&hd, HASH2MAC (hash)); if (ret < 0) { gnutls_assert (); return ret; } _gnutls_hash (&hd, text->data, text->size); _gnutls_hash_deinit (&hd, _digest); digest.data = _digest; digest.size = _gnutls_hash_get_algo_len (HASH2MAC (hash)); /* Encode the digest as a DigestInfo */ if ((ret = encode_ber_digest_info (hash, &digest, &info)) != 0) { gnutls_assert (); return ret; } if ((ret = _gnutls_sign (GNUTLS_PK_RSA, params, params_len, &info, signature)) < 0) { gnutls_assert (); _gnutls_free_datum (&info); return ret; } _gnutls_free_datum (&info); return 0; }
/* Free all the entry parameters, except if g and n are * the static ones defined in gnutls.h */ void _gnutls_srp_entry_free(SRP_PWD_ENTRY * entry) { _gnutls_free_key_datum(&entry->v); _gnutls_free_datum(&entry->salt); if ((entry->g.data != gnutls_srp_1024_group_generator.data) && (entry->g.data != gnutls_srp_3072_group_generator.data)) _gnutls_free_datum(&entry->g); if (entry->n.data != gnutls_srp_1024_group_prime.data && entry->n.data != gnutls_srp_1536_group_prime.data && entry->n.data != gnutls_srp_2048_group_prime.data && entry->n.data != gnutls_srp_3072_group_prime.data && entry->n.data != gnutls_srp_4096_group_prime.data) _gnutls_free_datum(&entry->n); gnutls_free(entry->username); gnutls_free(entry); }
/** * gnutls_privkey_sign_data: * @signer: Holds the key * @hash: should be a digest algorithm * @flags: Zero or one of %gnutls_privkey_flags_t * @data: holds the data to be signed * @signature: will contain the signature allocate with gnutls_malloc() * * This function will sign the given data using a signature algorithm * supported by the private key. Signature algorithms are always used * together with a hash functions. Different hash functions may be * used for the RSA algorithm, but only the SHA family for the DSA keys. * * You may use gnutls_pubkey_get_preferred_hash_algorithm() to determine * the hash algorithm. * * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a * negative error value. * * Since: 2.12.0 **/ int gnutls_privkey_sign_data(gnutls_privkey_t signer, gnutls_digest_algorithm_t hash, unsigned int flags, const gnutls_datum_t * data, gnutls_datum_t * signature) { int ret; gnutls_datum_t digest; const mac_entry_st *me = mac_to_entry(hash); if (flags & GNUTLS_PRIVKEY_SIGN_FLAG_TLS1_RSA) return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); ret = pk_hash_data(signer->pk_algorithm, me, NULL, data, &digest); if (ret < 0) { gnutls_assert(); return ret; } ret = pk_prepare_hash(signer->pk_algorithm, me, &digest); if (ret < 0) { gnutls_assert(); goto cleanup; } ret = gnutls_privkey_sign_raw_data(signer, flags, &digest, signature); _gnutls_free_datum(&digest); if (ret < 0) { gnutls_assert(); return ret; } return 0; cleanup: _gnutls_free_datum(&digest); return ret; }
/* returns ciphertext which contains the headers too. This also * calculates the size in the header field. * * If random pad != 0 then the random pad data will be appended. */ int _gnutls_encrypt (gnutls_session_t session, const opaque * headers, size_t headers_size, const opaque * data, size_t data_size, opaque * ciphertext, size_t ciphertext_size, content_type_t type, int random_pad, record_parameters_st * params) { gnutls_datum_t plain; gnutls_datum_t comp; int ret; int free_comp = 1; plain.data = (opaque *) data; plain.size = data_size; if (plain.size == 0 || is_write_comp_null (session) == 0) { comp = plain; free_comp = 0; } else { /* Here comp is allocated and must be * freed. */ ret = _gnutls_m_plaintext2compressed (session, &comp, &plain, params); if (ret < 0) { gnutls_assert (); return ret; } } ret = _gnutls_compressed2ciphertext (session, &ciphertext[headers_size], ciphertext_size - headers_size, comp, type, random_pad, params); if (free_comp) _gnutls_free_datum (&comp); if (ret < 0) { gnutls_assert (); return ret; } /* copy the headers */ memcpy (ciphertext, headers, headers_size); _gnutls_write_uint16 (ret, &ciphertext[3]); return ret + headers_size; }
/** * gnutls_x509_crq_sign2 - This function will sign a Certificate request with a key * @crq: should contain a gnutls_x509_crq_t structure * @key: holds a private key * @dig: The message digest to use. GNUTLS_DIG_SHA1 is the safe choice unless you know what you're doing. * @flags: must be 0 * * This function will sign the certificate request with a private key. * This must be the same key as the one used in gnutls_x509_crt_set_key() since a * certificate request is self signed. * * This must be the last step in a certificate request generation since all * the previously set parameters are now signed. * * Returns 0 on success. * **/ int gnutls_x509_crq_sign2 (gnutls_x509_crq_t crq, gnutls_x509_privkey_t key, gnutls_digest_algorithm_t dig, unsigned int flags) { int result; gnutls_datum_t signature; if (crq == NULL) { gnutls_assert (); return GNUTLS_E_INVALID_REQUEST; } /* Step 1. Self sign the request. */ result = _gnutls_x509_sign_tbs (crq->crq, "certificationRequestInfo", dig, key, &signature); if (result < 0) { gnutls_assert (); return result; } /* Step 2. write the signature (bits) */ result = asn1_write_value (crq->crq, "signature", signature.data, signature.size * 8); _gnutls_free_datum (&signature); if (result != ASN1_SUCCESS) { gnutls_assert (); return _gnutls_asn2err (result); } /* Step 3. Write the signatureAlgorithm field. */ result = _gnutls_x509_write_sig_params (crq->crq, "signatureAlgorithm", key->pk_algorithm, dig, key->params, key->params_size); if (result < 0) { gnutls_assert (); return result; } return 0; }
/** * gnutls_x509_crt_set_private_key_usage_period: * @crt: a certificate of type #gnutls_x509_crt_t * @activation: The activation time * @expiration: The expiration time * * This function will set the private key usage period extension (2.5.29.16). * * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a * negative error value. **/ int gnutls_x509_crt_set_private_key_usage_period(gnutls_x509_crt_t crt, time_t activation, time_t expiration) { int result; gnutls_datum_t der_data; ASN1_TYPE c2 = ASN1_TYPE_EMPTY; if (crt == NULL) { gnutls_assert(); return GNUTLS_E_INVALID_REQUEST; } result = asn1_create_element(_gnutls_get_pkix(), "PKIX1.PrivateKeyUsagePeriod", &c2); if (result != ASN1_SUCCESS) { gnutls_assert(); return _gnutls_asn2err(result); } result = _gnutls_x509_set_time(c2, "notBefore", activation, 1); if (result < 0) { gnutls_assert(); goto cleanup; } result = _gnutls_x509_set_time(c2, "notAfter", expiration, 1); if (result < 0) { gnutls_assert(); goto cleanup; } result = _gnutls_x509_der_encode(c2, "", &der_data, 0); if (result < 0) { gnutls_assert(); goto cleanup; } result = _gnutls_x509_crt_set_extension(crt, "2.5.29.16", &der_data, 0); _gnutls_free_datum(&der_data); crt->use_extensions = 1; cleanup: asn1_delete_structure(&c2); return result; }
/** * gnutls_privkey_sign_data: * @signer: Holds the key * @digest: should be a digest algorithm * @flags: should be 0 for now * @data: holds the data to be signed * @signature: will contain the signature allocate with gnutls_malloc() * * This function will sign the given data using a signature algorithm * supported by the private key. Signature algorithms are always used * together with a hash functions. Different hash functions may be * used for the RSA algorithm, but only SHA-1 for the DSA keys. * * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a * negative error value. **/ int gnutls_privkey_sign_data2 (gnutls_privkey_t signer, gnutls_digest_algorithm_t hash, unsigned int flags, const gnutls_datum_t * data, gnutls_datum_t * signature) { int ret; gnutls_datum_t digest; ret = pk_hash_data (signer->pk_algorithm, hash, NULL, data, &digest); if (ret < 0) { gnutls_assert (); return ret; } ret = pk_prepare_hash (signer->pk_algorithm, hash, &digest); if (ret < 0) { gnutls_assert (); goto cleanup; } ret = _gnutls_privkey_sign_hash (signer, &digest, signature); _gnutls_free_datum (&digest); if (ret < 0) { gnutls_assert (); return ret; } return 0; cleanup: _gnutls_free_datum (&digest); return ret; }
/* Set the PSK premaster secret. */ int _gnutls_set_psk_session_key (gnutls_session_t session, gnutls_datum_t * ppsk /* key */, gnutls_datum_t * dh_secret) { gnutls_datum_t pwd_psk = { NULL, 0 }; size_t dh_secret_size; uint8_t * p; int ret; if (dh_secret == NULL) dh_secret_size = ppsk->size; else dh_secret_size = dh_secret->size; /* set the session key */ session->key.key.size = 4 + dh_secret_size + ppsk->size; session->key.key.data = gnutls_malloc (session->key.key.size); if (session->key.key.data == NULL) { gnutls_assert (); ret = GNUTLS_E_MEMORY_ERROR; goto error; } /* format of the premaster secret: * (uint16_t) psk_size * psk_size bytes of (0)s * (uint16_t) psk_size * the psk */ p = session->key.key.data; _gnutls_write_uint16 (dh_secret_size, p); p+=2; if (dh_secret == NULL) memset (p, 0, dh_secret_size); else memcpy (p, dh_secret->data, dh_secret->size); p += dh_secret_size; _gnutls_write_uint16 (ppsk->size, p); if (ppsk->data != NULL) memcpy (p+2, ppsk->data, ppsk->size); ret = 0; error: _gnutls_free_datum (&pwd_psk); 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; }
/* returns error if the certificate has different algorithm than * the given key parameters. */ static int _gnutls_check_key_cert_match (gnutls_certificate_credentials_t res) { gnutls_datum_t cid; gnutls_datum_t kid; unsigned pk = res->cert_list[res->ncerts - 1][0].subject_pk_algorithm; if (res->pkey[res->ncerts - 1].pk_algorithm != pk) { gnutls_assert (); return GNUTLS_E_CERTIFICATE_KEY_MISMATCH; } if (pk == GNUTLS_PK_RSA) { _gnutls_x509_write_rsa_params (res->pkey[res->ncerts - 1].params, res->pkey[res->ncerts - 1].params_size, &kid); _gnutls_x509_write_rsa_params (res-> cert_list[res->ncerts - 1][0].params, res->cert_list[res->ncerts - 1][0].params_size, &cid); } else if (pk == GNUTLS_PK_DSA) { _gnutls_x509_write_dsa_params (res->pkey[res->ncerts - 1].params, res->pkey[res->ncerts - 1].params_size, &kid); _gnutls_x509_write_dsa_params (res-> cert_list[res->ncerts - 1][0].params, res->cert_list[res->ncerts - 1][0].params_size, &cid); } if (cid.size != kid.size) { gnutls_assert (); _gnutls_free_datum (&kid); _gnutls_free_datum (&cid); return GNUTLS_E_CERTIFICATE_KEY_MISMATCH; } if (memcmp (kid.data, cid.data, kid.size) != 0) { gnutls_assert (); _gnutls_free_datum (&kid); _gnutls_free_datum (&cid); return GNUTLS_E_CERTIFICATE_KEY_MISMATCH; } _gnutls_free_datum (&kid); _gnutls_free_datum (&cid); return 0; }
int _gnutls_rsa_verify (const gnutls_datum_t * vdata, const gnutls_datum_t * ciphertext, gnutls_pk_params_st * params, int btype) { gnutls_datum_t plain; int ret; /* decrypt signature */ if ((ret = _gnutls_pkcs1_rsa_decrypt (&plain, ciphertext, params, btype)) < 0) { gnutls_assert (); return ret; } if (plain.size != vdata->size) { gnutls_assert (); _gnutls_free_datum (&plain); return GNUTLS_E_PK_SIG_VERIFY_FAILED; } if (memcmp (plain.data, vdata->data, plain.size) != 0) { gnutls_assert (); _gnutls_free_datum (&plain); return GNUTLS_E_PK_SIG_VERIFY_FAILED; } _gnutls_free_datum (&plain); return 0; /* ok */ }
/** * gnutls_x509_privkey_sign_data - This function will sign the given data using the private key params * @key: Holds the key * @digest: should be MD5 or SHA1 * @flags: should be 0 for now * @data: holds the data to be signed * @signature: will contain the signature * @signature_size: holds the size of signature (and will be replaced * by the new size) * * This function will sign the given data using a signature algorithm * supported by the private key. Signature algorithms are always used * together with a hash functions. Different hash functions may be * used for the RSA algorithm, but only SHA-1 for the DSA keys. * * If the buffer provided is not long enough to hold the output, then * *signature_size is updated and GNUTLS_E_SHORT_MEMORY_BUFFER will * be returned. * * In case of failure a negative value will be returned, and * 0 on success. * **/ int gnutls_x509_privkey_sign_data (gnutls_x509_privkey_t key, gnutls_digest_algorithm_t digest, unsigned int flags, const gnutls_datum_t * data, void *signature, size_t * signature_size) { int result; gnutls_datum_t sig = { NULL, 0 }; if (key == NULL) { gnutls_assert (); return GNUTLS_E_INVALID_REQUEST; } result = _gnutls_x509_sign (data, digest, key, &sig); if (result < 0) { gnutls_assert (); return result; } if (*signature_size < sig.size) { *signature_size = sig.size; _gnutls_free_datum (&sig); return GNUTLS_E_SHORT_MEMORY_BUFFER; } *signature_size = sig.size; memcpy (signature, sig.data, sig.size); _gnutls_free_datum (&sig); return 0; }
int _gnutls_gen_ecdh_common_client_kx_int(gnutls_session_t session, gnutls_buffer_st * data, gnutls_datum_t * psk_key) { int ret; gnutls_datum_t out; int curve = _gnutls_session_ecc_curve_get(session); /* generate temporal key */ ret = _gnutls_pk_generate_keys(GNUTLS_PK_EC, curve, &session->key.ecdh_params); if (ret < 0) return gnutls_assert_val(ret); ret = _gnutls_ecc_ansi_x963_export(curve, session->key.ecdh_params. params[ECC_X] /* x */ , session->key.ecdh_params. params[ECC_Y] /* y */ , &out); if (ret < 0) { gnutls_assert(); goto cleanup; } ret = _gnutls_buffer_append_data_prefix(data, 8, out.data, out.size); _gnutls_free_datum(&out); if (ret < 0) { gnutls_assert(); goto cleanup; } /* generate pre-shared key */ ret = calc_ecdh_key(session, psk_key, curve); if (ret < 0) { gnutls_assert(); goto cleanup; } ret = data->length; cleanup: gnutls_pk_params_clear(&session->key.ecdh_params); return ret; }
static int calc_ecdh_key( gnutls_session_t session, gnutls_datum_t * psk_key) { gnutls_pk_params_st pub; int ret; memset(&pub,0,sizeof(pub)); pub.params[ECC_PRIME] = session->key.ecdh_params.params[ECC_PRIME]; pub.params[ECC_ORDER] = session->key.ecdh_params.params[ECC_ORDER]; pub.params[ECC_A] = session->key.ecdh_params.params[ECC_A]; pub.params[ECC_B] = session->key.ecdh_params.params[ECC_B]; pub.params[ECC_GX] = session->key.ecdh_params.params[ECC_GX]; pub.params[ECC_GY] = session->key.ecdh_params.params[ECC_GY]; pub.params[ECC_X] = session->key.ecdh_x; pub.params[ECC_Y] = session->key.ecdh_y; if (psk_key == NULL) ret = _gnutls_pk_derive(GNUTLS_PK_EC, &session->key.key, &session->key.ecdh_params, &pub); else { gnutls_datum_t tmp_dh_key; ret = _gnutls_pk_derive(GNUTLS_PK_EC, &tmp_dh_key, &session->key.ecdh_params, &pub); if (ret < 0) { ret = gnutls_assert_val(ret); goto cleanup; } ret = _gnutls_set_psk_session_key (session, psk_key, &tmp_dh_key); _gnutls_free_datum (&tmp_dh_key); } if (ret < 0) { ret = gnutls_assert_val(ret); goto cleanup; } ret = 0; cleanup: /* no longer needed */ _gnutls_mpi_release (&session->key.ecdh_x); _gnutls_mpi_release (&session->key.ecdh_y); gnutls_pk_params_release( &session->key.ecdh_params); return ret; }
void _gnutls_gcert_deinit (gnutls_cert * cert) { int i; if (cert == NULL) return; for (i = 0; i < cert->params_size; i++) { _gnutls_mpi_release (&cert->params[i]); } _gnutls_free_datum (&cert->raw); }
/* 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_x509_crl_get_number - get the CRL number (extension) * @crl: should contain a #gnutls_x509_crl_t structure * @ret: The place where the number will be copied * @ret_size: Holds the size of the result field. * @critical: will be non zero if the extension is marked as critical * (may be null) * * This function will return the CRL number extension. This is * obtained by the CRL Number extension field (2.5.29.20). * * Returns: On success, %GNUTLS_E_SUCCESS is returned, otherwise a * negative value in case of an error. * * Since: 2.8.0 **/ int gnutls_x509_crl_get_number (gnutls_x509_crl_t crl, void *ret, size_t * ret_size, unsigned int *critical) { int result; gnutls_datum_t id; if (crl == NULL) { gnutls_assert (); return GNUTLS_E_INVALID_REQUEST; } if (ret) memset (ret, 0, *ret_size); else *ret_size = 0; if ((result = _gnutls_x509_crl_get_extension (crl, "2.5.29.20", 0, &id, critical)) < 0) { return result; } if (id.size == 0 || id.data == NULL) { gnutls_assert (); return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; } result = _gnutls_x509_ext_extract_number (ret, ret_size, id.data, id.size); _gnutls_free_datum (&id); if (result < 0) { gnutls_assert (); return result; } return 0; }