static int srp_username_callback (gnutls_session_t session, char **username, char **password) { if (srp_username == NULL || srp_passwd == NULL) { return -1; } *username = gnutls_strdup (srp_username); *password = gnutls_strdup (srp_passwd); return 0; }
/** * gnutls_psk_set_server_credentials_file - Used to set the password files, in a gnutls_psk_server_credentials_t structure * @res: is a #gnutls_psk_server_credentials_t structure. * @password_file: is the PSK password file (passwd.psk) * * This function sets the password file, in a * %gnutls_psk_server_credentials_t structure. This password file * holds usernames and keys and will be used for PSK authentication. * * Returns: %GNUTLS_E_SUCCESS on success, or an error code. **/ int gnutls_psk_set_server_credentials_file (gnutls_psk_server_credentials_t res, const char *password_file) { if (password_file == NULL) { gnutls_assert (); return GNUTLS_E_INVALID_REQUEST; } /* Check if the files can be opened */ if (_gnutls_file_exists (password_file) != 0) { gnutls_assert (); return GNUTLS_E_FILE_ERROR; } res->password_file = gnutls_strdup (password_file); if (res->password_file == NULL) { gnutls_assert (); return GNUTLS_E_MEMORY_ERROR; } return 0; }
/** * gnutls_ext_register: * @name: the name of the extension to register * @type: the numeric id of the extension * @parse_type: the parse type of the extension (see gnutls_ext_parse_type_t) * @recv_func: a function to receive the data * @send_func: a function to send the data * @deinit_func: a function deinitialize any private data * @pack_func: a function which serializes the extension's private data (used on session packing for resumption) * @unpack_func: a function which will deserialize the extension's private data * * This function will register a new extension type. The extension will remain * registered until gnutls_global_deinit() is called. If the extension type * is already registered then %GNUTLS_E_ALREADY_REGISTERED will be returned. * * Each registered extension can store temporary data into the gnutls_session_t * structure using gnutls_ext_set_data(), and they can be retrieved using * gnutls_ext_get_data(). * * This function is not thread safe. * * Returns: %GNUTLS_E_SUCCESS on success, otherwise a negative error code. * * Since: 3.4.0 **/ int gnutls_ext_register(const char *name, int type, gnutls_ext_parse_type_t parse_type, gnutls_ext_recv_func recv_func, gnutls_ext_send_func send_func, gnutls_ext_deinit_data_func deinit_func, gnutls_ext_pack_func pack_func, gnutls_ext_unpack_func unpack_func) { extension_entry_st tmp_mod; int ret; unsigned i; for (i = 0; i < extfunc_size; i++) { if (extfunc[i].type == type) return gnutls_assert_val(GNUTLS_E_ALREADY_REGISTERED); } memset(&tmp_mod, 0, sizeof(tmp_mod)); tmp_mod.name = gnutls_strdup(name); tmp_mod.free_name = 1; tmp_mod.type = type; tmp_mod.parse_type = parse_type; tmp_mod.recv_func = recv_func; tmp_mod.send_func = send_func; tmp_mod.deinit_func = deinit_func; tmp_mod.pack_func = pack_func; tmp_mod.unpack_func = unpack_func; ret = ext_register(&tmp_mod); if (ret < 0) { gnutls_free((void*)tmp_mod.name); } return ret; }
/** * gnutls_pkcs12_bag_set_friendly_name - This function sets a friendly name into the bag element * @bag: The bag * @indx: The bag's element to add the id * @name: the name * * This function will add the given key friendly name, to the specified, by the index, bag * element. The name will be encoded as a 'Friendly name' bag attribute, * which is usually used to set a user name to the local private key and the certificate pair. * * Returns 0 on success, or a negative value on error. * **/ int gnutls_pkcs12_bag_set_friendly_name (gnutls_pkcs12_bag_t bag, int indx, const char *name) { if (bag == NULL) { gnutls_assert (); return GNUTLS_E_INVALID_REQUEST; } if (indx > bag->bag_elements - 1) { gnutls_assert (); return GNUTLS_E_INVALID_REQUEST; } bag->element[indx].friendly_name = gnutls_strdup (name); if (name == NULL) { gnutls_assert (); return GNUTLS_E_MEMORY_ERROR; } return 0; }
/** * gnutls_psk_set_server_credentials_hint - Set a identity hint, in a %gnutls_psk_server_credentials_t structure * @res: is a #gnutls_psk_server_credentials_t structure. * @hint: is the PSK identity hint string * * This function sets the identity hint, in a * %gnutls_psk_server_credentials_t structure. This hint is sent to * the client to help it chose a good PSK credential (i.e., username * and password). * * Returns: %GNUTLS_E_SUCCESS on success, or an error code. * * Since: 2.4.0 **/ int gnutls_psk_set_server_credentials_hint (gnutls_psk_server_credentials_t res, const char *hint) { res->hint = gnutls_strdup (hint); if (res->hint == NULL) { gnutls_assert (); return GNUTLS_E_MEMORY_ERROR; } return 0; }
/** * gnutls_certificate_set_ocsp_status_request_file: * @session: is a #gnutls_session_t structure. * @response_file: a filename of the OCSP response * @flags: should be zero * * This function sets the filename of an OCSP response, that will be * sent to the client if requests an OCSP certificate status. This is * a convenience function which is inefficient on busy servers since * the file is opened on every access. Use * gnutls_certificate_set_ocsp_status_request_function() to fine-tune * file accesses. * * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, * otherwise a negative error code is returned. * * Since: 3.1.3 **/ int gnutls_certificate_set_ocsp_status_request_file (gnutls_certificate_credentials_t sc, const char *response_file, unsigned int flags) { sc->ocsp_func = file_ocsp_func; sc->ocsp_func_ptr = sc; sc->ocsp_response_file = gnutls_strdup(response_file); if (sc->ocsp_response_file == NULL) return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); return 0; }
/** * gnutls_srp_set_client_credentials: * @res: is a #gnutls_srp_client_credentials_t type. * @username: is the user's userid * @password: is the user's password * * This function sets the username and password, in a * #gnutls_srp_client_credentials_t type. Those will be used in * SRP authentication. @username and @password should be ASCII * strings or UTF-8 strings prepared using the "SASLprep" profile of * "stringprep". * * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, or an * error code. **/ int gnutls_srp_set_client_credentials(gnutls_srp_client_credentials_t res, const char *username, const char *password) { if (username == NULL || password == NULL) { gnutls_assert(); return GNUTLS_E_INVALID_REQUEST; } res->username = gnutls_strdup(username); if (res->username == NULL) return GNUTLS_E_MEMORY_ERROR; res->password = gnutls_strdup(password); if (res->password == NULL) { gnutls_free(res->username); return GNUTLS_E_MEMORY_ERROR; } return 0; }
static int srp_username_callback (gnutls_session session, unsigned int times, char **username, char **password) { if (srp_username == NULL || srp_passwd == NULL) { return -1; } /* We should ask here the user for his SRP username * and password. */ if (times == 1) { *username = gnutls_strdup (srp_username); *password = gnutls_strdup (srp_passwd); return 0; } else /* At the first time return username and password, if * the kx_priority[0] is an SRP method. */ if (times == 0 && (kx_priority[0] == GNUTLS_KX_SRP || kx_priority[0] == GNUTLS_KX_SRP_RSA || kx_priority[0] == GNUTLS_KX_SRP_DSS)) { *username = gnutls_strdup (srp_username); *password = gnutls_strdup (srp_passwd); return 0; } return -1; }
static krb5_principal_data *name_to_principal(const char *_name) { krb5_principal_data *princ; char *p, *p2, *sp; unsigned pos = 0; char *name = NULL; princ = gnutls_calloc(1, sizeof(struct krb5_principal_data)); if (princ == NULL) return NULL; name = gnutls_strdup(_name); if (name == NULL) { gnutls_assert(); goto fail; } p = strrchr(name, '@'); p2 = strchr(name, '@'); if (p == NULL) { /* unknown name type */ gnutls_assert(); goto fail; } princ->realm = gnutls_strdup(p + 1); if (princ->realm == NULL) { gnutls_assert(); goto fail; } *p = 0; if (p == p2) { p = strtok_r(name, "/", &sp); while (p) { if (pos == MAX_COMPONENTS) { _gnutls_debug_log ("%s: Cannot parse names with more than %d components\n", __func__, MAX_COMPONENTS); goto fail; } princ->data[pos] = gnutls_strdup(p); if (princ->data[pos] == NULL) { gnutls_assert(); goto fail; } princ->length++; pos++; p = strtok_r(NULL, "/", &sp); } if ((princ->length == 2) && (strcmp(princ->data[0], "krbtgt") == 0)) { princ->type = 2; /* KRB_NT_SRV_INST */ } else { princ->type = 1; /* KRB_NT_PRINCIPAL */ } } else { /* enterprise */ princ->data[0] = gnutls_strdup(name); if (princ->data[0] == NULL) { gnutls_assert(); goto fail; } princ->length++; princ->type = 10; /* KRB_NT_ENTERPRISE */ } goto cleanup; fail: cleanup_principal(princ); princ = NULL; cleanup: gnutls_free(name); return princ; }
static int psk_callback (gnutls_session_t session, char **username, gnutls_datum_t * key) { const char *hint = gnutls_psk_client_get_hint (session); char *passwd; int ret; printf ("- PSK client callback. "); if (hint) printf ("PSK hint '%s'\n", hint); else printf ("No PSK hint\n"); if (info.psk_username) *username = gnutls_strdup (info.psk_username); else { char *tmp = NULL; size_t n; ssize_t len; printf ("Enter PSK identity: "); fflush (stdout); len = getline (&tmp, &n, stdin); if (tmp == NULL) { fprintf (stderr, "No username given, aborting...\n"); return GNUTLS_E_INSUFFICIENT_CREDENTIALS; } if (tmp[strlen (tmp) - 1] == '\n') tmp[strlen (tmp) - 1] = '\0'; if (tmp[strlen (tmp) - 1] == '\r') tmp[strlen (tmp) - 1] = '\0'; *username = gnutls_strdup (tmp); free (tmp); } if (!*username) return GNUTLS_E_MEMORY_ERROR; passwd = getpass ("Enter password: "******"No password given, aborting...\n"); return GNUTLS_E_INSUFFICIENT_CREDENTIALS; } ret = gnutls_psk_netconf_derive_key (passwd, *username, hint ? hint : "", key); if (ret < 0) { fprintf (stderr, "Error deriving password: %s\n", gnutls_strerror (ret)); gnutls_free (*username); return ret; } if (info.debug) { char hexkey[41]; size_t res_size = sizeof (hexkey); gnutls_hex_encode (key, hexkey, &res_size); fprintf (stderr, "PSK username: %s\n", *username); fprintf (stderr, "PSK hint: %s\n", hint); fprintf (stderr, "PSK key: %s\n", hexkey); } return 0; }
/* this function parses tpasswd.conf file. Format is: * string(username):base64(v):base64(salt):int(index) */ static int pwd_put_values (SRP_PWD_ENTRY * entry, char *str) { char *p; int len, ret; opaque *verifier; size_t verifier_size; int indx; p = strrchr (str, ':'); /* we have index */ if (p == NULL) { gnutls_assert (); return GNUTLS_E_SRP_PWD_PARSING_ERROR; } *p = '\0'; p++; indx = atoi (p); if (indx == 0) { gnutls_assert (); return GNUTLS_E_SRP_PWD_PARSING_ERROR; } /* now go for salt */ p = strrchr (str, ':'); /* we have salt */ if (p == NULL) { gnutls_assert (); return GNUTLS_E_SRP_PWD_PARSING_ERROR; } *p = '\0'; p++; len = strlen (p); entry->salt.size = _gnutls_sbase64_decode (p, len, &entry->salt.data); if (entry->salt.size <= 0) { gnutls_assert (); return GNUTLS_E_SRP_PWD_PARSING_ERROR; } /* now go for verifier */ p = strrchr (str, ':'); /* we have verifier */ if (p == NULL) { _gnutls_free_datum (&entry->salt); return GNUTLS_E_SRP_PWD_PARSING_ERROR; } *p = '\0'; p++; len = strlen (p); ret = _gnutls_sbase64_decode (p, len, &verifier); if (ret <= 0) { gnutls_assert (); _gnutls_free_datum (&entry->salt); return GNUTLS_E_SRP_PWD_PARSING_ERROR; } verifier_size = ret; entry->v.data = verifier; entry->v.size = verifier_size; /* now go for username */ *p = '\0'; entry->username = gnutls_strdup (str); if (entry->username == NULL) { _gnutls_free_datum (&entry->salt); _gnutls_free_datum (&entry->v); gnutls_assert (); return GNUTLS_E_MEMORY_ERROR; } return indx; }
/** * gnutls_priority_init - Sets priorities for the cipher suites supported by gnutls. * @priority_cache: is a #gnutls_prioritity_t structure. * @priorities: is a string describing priorities * @err_pos: In case of an error this will have the position in the string the error occured * * Sets priorities for the ciphers, key exchange methods, macs and * compression methods. This is to avoid using the * gnutls_*_priority() functions. * * The #priorities option allows you to specify a semi-colon * separated list of the cipher priorities to enable. * * Unless the first keyword is "NONE" the defaults are: * Protocols: TLS1.1, TLS1.0, and SSL3.0. * Compression: NULL. * Certificate types: X.509, OpenPGP. * * You can also use predefined sets of ciphersuites: "PERFORMANCE" * all the "secure" ciphersuites are enabled, limited to 128 bit * ciphers and sorted by terms of speed performance. * * "NORMAL" option enables all "secure" ciphersuites. The 256-bit ciphers * are included as a fallback only. The ciphers are sorted by security margin. * * "SECURE128" flag enables all "secure" ciphersuites with ciphers up to * 128 bits, sorted by security margin. * * "SECURE256" flag enables all "secure" ciphersuites including the 256 bit * ciphers, sorted by security margin. * * "EXPORT" all the ciphersuites are enabled, including the * low-security 40 bit ciphers. * * "NONE" nothing is enabled. This disables even protocols and * compression methods. * * Special keywords: * '!' or '-' appended with an algorithm will remove this algorithm. * '+' appended with an algorithm will add this algorithm. * '%COMPAT' will enable compatibility features for a server. * * To avoid collisions in order to specify a compression algorithm in * this string you have to prefix it with "COMP-", protocol versions * with "VERS-" and certificate types with "CTYPE-". All other * algorithms don't need a prefix. * * For key exchange algorithms when in NORMAL or SECURE levels the * perfect forward secrecy algorithms take precendence of the other * protocols. In all cases all the supported key exchange algorithms * are enabled (except for the RSA-EXPORT which is only enabled in * EXPORT level). * * Note that although one can select very long key sizes (such as 256 bits) * for symmetric algorithms, to actually increase security the public key * algorithms have to use longer key sizes as well. * * Examples: "NORMAL:!AES-128-CBC", * "EXPORT:!VERS-TLS1.0:+COMP-DEFLATE:+CTYPE-OPENPGP", * "NONE:+VERS-TLS1.0:+AES-128-CBC:+RSA:+SHA1:+COMP-NULL", "NORMAL", * "NORMAL:%COMPAT". * * Returns: On syntax error GNUTLS_E_INVALID_REQUEST is returned and * 0 on success. **/ int gnutls_priority_init (gnutls_priority_t * priority_cache, const char *priorities, const char **err_pos) { char *broken_list[MAX_ELEMENTS]; int broken_list_size, i, j; char *darg; int algo; rmadd_func *fn; *priority_cache = gnutls_calloc (1, sizeof (struct gnutls_priority_st)); if (*priority_cache == NULL) { gnutls_assert (); return GNUTLS_E_MEMORY_ERROR; } if (priorities == NULL) priorities = "NORMAL"; darg = gnutls_strdup (priorities); if (darg == NULL) { gnutls_assert (); return GNUTLS_E_MEMORY_ERROR; } break_comma_list (darg, broken_list, &broken_list_size, MAX_ELEMENTS, ':'); /* This is our default set of protocol version, certificate types and * compression methods. */ if (strcasecmp (broken_list[0], "NONE") != 0) { _set_priority (&(*priority_cache)->protocol, protocol_priority); _set_priority (&(*priority_cache)->compression, comp_priority); _set_priority (&(*priority_cache)->cert_type, cert_type_priority); } for (i = 0; i < broken_list_size; i++) { if (strcasecmp (broken_list[i], "PERFORMANCE") == 0) { _set_priority (&(*priority_cache)->cipher, cipher_priority_performance); _set_priority (&(*priority_cache)->kx, kx_priority_performance); _set_priority (&(*priority_cache)->mac, mac_priority_performance); } else if (strcasecmp (broken_list[i], "NORMAL") == 0) { _set_priority (&(*priority_cache)->cipher, cipher_priority_normal); _set_priority (&(*priority_cache)->kx, kx_priority_secure); _set_priority (&(*priority_cache)->mac, mac_priority_secure); } else if (strcasecmp (broken_list[i], "SECURE256") == 0 || strcasecmp (broken_list[i], "SECURE") == 0) { _set_priority (&(*priority_cache)->cipher, cipher_priority_secure256); _set_priority (&(*priority_cache)->kx, kx_priority_secure); _set_priority (&(*priority_cache)->mac, mac_priority_secure); } else if (strcasecmp (broken_list[i], "SECURE128") == 0) { _set_priority (&(*priority_cache)->cipher, cipher_priority_secure128); _set_priority (&(*priority_cache)->kx, kx_priority_secure); _set_priority (&(*priority_cache)->mac, mac_priority_secure); } else if (strcasecmp (broken_list[i], "EXPORT") == 0) { _set_priority (&(*priority_cache)->cipher, cipher_priority_export); _set_priority (&(*priority_cache)->kx, kx_priority_export); _set_priority (&(*priority_cache)->mac, mac_priority_secure); } /* now check if the element is something like -ALGO */ else if (broken_list[i][0] == '!' || broken_list[i][0] == '+' || broken_list[i][0] == '-') { if (broken_list[i][0] == '+') fn = prio_add; else fn = prio_remove; if ((algo = gnutls_mac_get_id (&broken_list[i][1])) != GNUTLS_MAC_UNKNOWN) fn (&(*priority_cache)->mac, algo); else if ((algo = gnutls_cipher_get_id (&broken_list[i][1])) != GNUTLS_CIPHER_UNKNOWN) fn (&(*priority_cache)->cipher, algo); else if ((algo = gnutls_kx_get_id (&broken_list[i][1])) != GNUTLS_KX_UNKNOWN) fn (&(*priority_cache)->kx, algo); else if (strncasecmp (&broken_list[i][1], "VERS-", 5) == 0) { if ((algo = gnutls_protocol_get_id (&broken_list[i][6])) != GNUTLS_VERSION_UNKNOWN) fn (&(*priority_cache)->protocol, algo); } /* now check if the element is something like -ALGO */ else if (strncasecmp (&broken_list[i][1], "COMP-", 5) == 0) { if ((algo = gnutls_compression_get_id (&broken_list[i][6])) != GNUTLS_COMP_UNKNOWN) fn (&(*priority_cache)->compression, algo); } /* now check if the element is something like -ALGO */ else if (strncasecmp (&broken_list[i][1], "CTYPE-", 6) == 0) { if ((algo = gnutls_certificate_type_get_id (&broken_list[i][7])) != GNUTLS_CRT_UNKNOWN) fn (&(*priority_cache)->cert_type, algo); } /* now check if the element is something like -ALGO */ else goto error; } else if (broken_list[i][0] == '%') { if (strcasecmp (&broken_list[i][1], "COMPAT") == 0) (*priority_cache)->no_padding = 1; else goto error; } else goto error; } gnutls_free (darg); return 0; error: if (err_pos != NULL && i < broken_list_size) { *err_pos = priorities; for (j = 0; j < i; j++) { (*err_pos) += strlen (broken_list[j]) + 1; } } gnutls_free (darg); return GNUTLS_E_INVALID_REQUEST; }
/** * gnutls_x509_trust_list_add_trust_file: * @list: The list * @ca_file: A file containing a list of CAs (optional) * @crl_file: A file containing a list of CRLs (optional) * @type: The format of the certificates * @tl_flags: flags from %gnutls_trust_list_flags_t * @tl_vflags: gnutls_certificate_verify_flags if flags specifies GNUTLS_TL_VERIFY_CRL * * This function will add the given certificate authorities * to the trusted list. PKCS #11 URLs are also accepted, instead * of files, by this function. A PKCS #11 URL implies a trust * database (a specially marked module in p11-kit); the URL "pkcs11:" * implies all trust databases in the system. Only a single URL specifying * trust databases can be set; they cannot be stacked with multiple calls. * * Returns: The number of added elements is returned. * * Since: 3.1 **/ int gnutls_x509_trust_list_add_trust_file(gnutls_x509_trust_list_t list, const char *ca_file, const char *crl_file, gnutls_x509_crt_fmt_t type, unsigned int tl_flags, unsigned int tl_vflags) { gnutls_datum_t cas = { NULL, 0 }; gnutls_datum_t crls = { NULL, 0 }; size_t size; int ret; if (ca_file != NULL) { #ifdef ENABLE_PKCS11 if (strncmp(ca_file, "pkcs11:", 7) == 0) { unsigned pcrt_list_size = 0; /* in case of a token URL import it as a PKCS #11 token, * otherwise import the individual certificates. */ if (is_pkcs11_url_object(ca_file) != 0) { return add_trust_list_pkcs11_object_url(list, ca_file, tl_flags); } else { /* token */ if (list->pkcs11_token != NULL) return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); list->pkcs11_token = gnutls_strdup(ca_file); /* enumerate the certificates */ ret = gnutls_pkcs11_obj_list_import_url(NULL, &pcrt_list_size, ca_file, (GNUTLS_PKCS11_OBJ_FLAG_CRT|GNUTLS_PKCS11_OBJ_FLAG_MARK_CA|GNUTLS_PKCS11_OBJ_FLAG_MARK_TRUSTED), 0); if (ret < 0 && ret != GNUTLS_E_SHORT_MEMORY_BUFFER) return gnutls_assert_val(ret); return pcrt_list_size; } } else #endif { cas.data = (void *) read_binary_file(ca_file, &size); if (cas.data == NULL) { gnutls_assert(); return GNUTLS_E_FILE_ERROR; } cas.size = size; } } if (crl_file) { crls.data = (void *) read_binary_file(crl_file, &size); if (crls.data == NULL) { gnutls_assert(); return GNUTLS_E_FILE_ERROR; } crls.size = size; } ret = gnutls_x509_trust_list_add_trust_mem(list, &cas, &crls, type, tl_flags, tl_vflags); free(crls.data); free(cas.data); return ret; }
/* extract the proxyCertInfo from the DER encoded extension */ int _gnutls_x509_ext_extract_proxyCertInfo (int *pathLenConstraint, char **policyLanguage, char **policy, size_t * sizeof_policy, uint8_t * extnValue, int extnValueLen) { ASN1_TYPE ext = ASN1_TYPE_EMPTY; int result; gnutls_datum_t value; if ((result = asn1_create_element (_gnutls_get_pkix (), "PKIX1.ProxyCertInfo", &ext)) != ASN1_SUCCESS) { gnutls_assert (); return _gnutls_asn2err (result); } result = asn1_der_decoding (&ext, extnValue, extnValueLen, NULL); if (result != ASN1_SUCCESS) { gnutls_assert (); asn1_delete_structure (&ext); return _gnutls_asn2err (result); } if (pathLenConstraint) { result = _gnutls_x509_read_uint (ext, "pCPathLenConstraint", (unsigned int*)pathLenConstraint); if (result == GNUTLS_E_ASN1_ELEMENT_NOT_FOUND) *pathLenConstraint = -1; else if (result != GNUTLS_E_SUCCESS) { asn1_delete_structure (&ext); return _gnutls_asn2err (result); } } result = _gnutls_x509_read_value (ext, "proxyPolicy.policyLanguage", &value); if (result < 0) { gnutls_assert (); asn1_delete_structure (&ext); return result; } if (policyLanguage) *policyLanguage = gnutls_strdup ((char*)value.data); result = _gnutls_x509_read_value (ext, "proxyPolicy.policy", &value); if (result == GNUTLS_E_ASN1_ELEMENT_NOT_FOUND) { if (policy) *policy = NULL; if (sizeof_policy) *sizeof_policy = 0; } else if (result < 0) { gnutls_assert (); asn1_delete_structure (&ext); return result; } else { if (policy) *policy = (char*)value.data; if (sizeof_policy) *sizeof_policy = value.size; } asn1_delete_structure (&ext); return 0; }
static int psk_callback (gnutls_session_t session, char **username, gnutls_datum_t * key) { const char *hint = gnutls_psk_client_get_hint (session); unsigned char *rawkey; char *passwd; int ret; size_t res_size; gnutls_datum_t tmp; printf ("- PSK client callback. "); if (hint) printf ("PSK hint '%s'\n", hint); else printf ("No PSK hint\n"); if (info.psk_username) *username = gnutls_strdup (info.psk_username); else { char *tmp = NULL; size_t n; printf ("Enter PSK identity: "); fflush (stdout); getline (&tmp, &n, stdin); if (tmp == NULL) { fprintf (stderr, "No username given, aborting...\n"); return GNUTLS_E_INSUFFICIENT_CREDENTIALS; } if (tmp[strlen (tmp) - 1] == '\n') tmp[strlen (tmp) - 1] = '\0'; if (tmp[strlen (tmp) - 1] == '\r') tmp[strlen (tmp) - 1] = '\0'; *username = gnutls_strdup (tmp); free (tmp); } if (!*username) return GNUTLS_E_MEMORY_ERROR; passwd = getpass ("Enter key: "); if (passwd == NULL) { fprintf (stderr, "No key given, aborting...\n"); return GNUTLS_E_INSUFFICIENT_CREDENTIALS; } tmp.data = passwd; tmp.size = strlen (passwd); res_size = tmp.size / 2 + 1; rawkey = gnutls_malloc (res_size); if (rawkey == NULL) return GNUTLS_E_MEMORY_ERROR; ret = gnutls_hex_decode (&tmp, rawkey, &res_size); if (ret < 0) { fprintf (stderr, "Error deriving password: %s\n", gnutls_strerror (ret)); gnutls_free (*username); return ret; } key->data = rawkey; key->size = res_size; if (info.debug) { char hexkey[41]; res_size = sizeof (hexkey); gnutls_hex_encode (key, hexkey, &res_size); fprintf (stderr, "PSK username: %s\n", *username); fprintf (stderr, "PSK hint: %s\n", hint); fprintf (stderr, "PSK key: %s\n", hexkey); } return 0; }
/** * gnutls_utf8_password_normalize: * @password: contain the UTF-8 formatted password * @plen: the length of the provided password * @out: the result in an null-terminated allocated string * @flags: should be zero * * This function will convert the provided UTF-8 password according * to the normalization rules in RFC7613. * * If the flag %GNUTLS_UTF8_IGNORE_ERRS is specified, any UTF-8 encoding * errors will be ignored, and in that case the output will be a copy of the input. * * Returns: %GNUTLS_E_INVALID_UTF8_STRING on invalid UTF-8 data, or 0 on success. * * Since: 3.5.7 **/ int gnutls_utf8_password_normalize(const unsigned char *password, unsigned plen, gnutls_datum_t *out, unsigned flags) { size_t ucs4_size = 0, nrm_size = 0; size_t final_size = 0; uint8_t *final = NULL; uint32_t *ucs4 = NULL; uint32_t *nrm = NULL; uint8_t *nrmu8 = NULL; int ret; if (plen == 0) { out->data = (uint8_t*)gnutls_strdup(""); out->size = 0; if (out->data == NULL) return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); return 0; } /* check for invalid UTF-8 */ if (u8_check((uint8_t*)password, plen) != NULL) { gnutls_assert(); if (flags & GNUTLS_UTF8_IGNORE_ERRS) { raw_copy: out->data = gnutls_malloc(plen+1); if (out->data == NULL) return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); out->size = plen; memcpy(out->data, password, plen); out->data[plen] = 0; return 0; } else { return GNUTLS_E_INVALID_UTF8_STRING; } } /* convert to UTF-32 */ ucs4 = u8_to_u32((uint8_t*)password, plen, NULL, &ucs4_size); if (ucs4 == NULL) { gnutls_assert(); ret = GNUTLS_E_PARSING_ERROR; goto fail; } ret = check_for_valid_freeformclass(ucs4, ucs4_size); if (ret < 0) { gnutls_assert(); if (flags & GNUTLS_UTF8_IGNORE_ERRS) { free(ucs4); goto raw_copy; } if (ret == GNUTLS_E_INVALID_UTF8_STRING) ret = GNUTLS_E_INVALID_PASSWORD_STRING; goto fail; } /* normalize to NFC */ nrm = u32_normalize(UNINORM_NFC, ucs4, ucs4_size, NULL, &nrm_size); if (nrm == NULL) { gnutls_assert(); ret = GNUTLS_E_INVALID_PASSWORD_STRING; goto fail; } /* convert back to UTF-8 */ final_size = 0; nrmu8 = u32_to_u8(nrm, nrm_size, NULL, &final_size); if (nrmu8 == NULL) { gnutls_assert(); ret = GNUTLS_E_INVALID_PASSWORD_STRING; goto fail; } /* copy to output with null terminator */ final = gnutls_malloc(final_size+1);
/** * gnutls_pkcs11_privkey_import_url: * @pkey: The private key * @url: a PKCS 11 url identifying the key * @flags: Or sequence of GNUTLS_PKCS11_OBJ_* flags * * This function will "import" a PKCS 11 URL identifying a private * key to the #gnutls_pkcs11_privkey_t type. In reality since * in most cases keys cannot be exported, the private key structure * is being associated with the available operations on the token. * * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a * negative error value. **/ int gnutls_pkcs11_privkey_import_url(gnutls_pkcs11_privkey_t pkey, const char *url, unsigned int flags) { int ret; struct ck_attribute *attr; struct ck_attribute a[4]; ck_key_type_t key_type; ck_bool_t reauth = 0; PKCS11_CHECK_INIT; memset(&pkey->sinfo, 0, sizeof(pkey->sinfo)); if (pkey->url) { gnutls_free(pkey->url); pkey->url = NULL; } if (pkey->uinfo) { p11_kit_uri_free(pkey->uinfo); pkey->uinfo = NULL; } pkey->url = gnutls_strdup(url); if (pkey->url == NULL) return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); ret = pkcs11_url_to_info(pkey->url, &pkey->uinfo, flags|GNUTLS_PKCS11_OBJ_FLAG_EXPECT_PRIVKEY); if (ret < 0) { gnutls_assert(); goto cleanup; } pkey->flags = flags; attr = p11_kit_uri_get_attribute(pkey->uinfo, CKA_CLASS); if (!attr || attr->value_len != sizeof(ck_object_class_t) || *(ck_object_class_t *) attr->value != CKO_PRIVATE_KEY) { gnutls_assert(); ret = GNUTLS_E_INVALID_REQUEST; goto cleanup; } attr = p11_kit_uri_get_attribute(pkey->uinfo, CKA_ID); if (!attr) { attr = p11_kit_uri_get_attribute(pkey->uinfo, CKA_LABEL); if (!attr) { gnutls_assert(); ret = GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; goto cleanup; } } FIND_OBJECT(pkey); pkey->pk_algorithm = GNUTLS_PK_UNKNOWN; a[0].type = CKA_KEY_TYPE; a[0].value = &key_type; a[0].value_len = sizeof(key_type); if (pkcs11_get_attribute_value(pkey->sinfo.module, pkey->sinfo.pks, pkey->ref, a, 1) == CKR_OK) { pkey->pk_algorithm = key_type_to_pk(key_type); } if (pkey->pk_algorithm == GNUTLS_PK_UNKNOWN) { _gnutls_debug_log ("Cannot determine PKCS #11 key algorithm\n"); ret = GNUTLS_E_UNKNOWN_ALGORITHM; goto cleanup; } a[0].type = CKA_ALWAYS_AUTHENTICATE; a[0].value = &reauth; a[0].value_len = sizeof(reauth); if (pkcs11_get_attribute_value(pkey->sinfo.module, pkey->sinfo.pks, pkey->ref, a, 1) == CKR_OK) { pkey->reauth = reauth; } ret = 0; return ret; cleanup: if (pkey->uinfo != NULL) { p11_kit_uri_free(pkey->uinfo); pkey->uinfo = NULL; } gnutls_free(pkey->url); pkey->url = NULL; return ret; }
/** * gnutls_priority_init: * @priority_cache: is a #gnutls_prioritity_t structure. * @priorities: is a string describing priorities * @err_pos: In case of an error this will have the position in the string the error occured * * Sets priorities for the ciphers, key exchange methods, macs and * compression methods. * * The #priorities option allows you to specify a colon * separated list of the cipher priorities to enable. * Some keywords are defined to provide quick access * to common preferences. * * Unless there is a special need, using "NORMAL" or "NORMAL:%COMPAT" for compatibility * is recommended. * * "PERFORMANCE" means all the "secure" ciphersuites are enabled, * limited to 128 bit ciphers and sorted by terms of speed * performance. * * "NORMAL" means all "secure" ciphersuites. The 256-bit ciphers are * included as a fallback only. The ciphers are sorted by security * margin. * * "PFS" means all "secure" ciphersuites that support perfect forward secrecy. * The 256-bit ciphers are included as a fallback only. * The ciphers are sorted by security margin. * * "SECURE128" means all "secure" ciphersuites of security level 128-bit * or more. * * "SECURE192" means all "secure" ciphersuites of security level 192-bit * or more. * * "SUITEB128" means all the NSA SuiteB ciphersuites with security level * of 128. * * "SUITEB192" means all the NSA SuiteB ciphersuites with security level * of 192. * * "EXPORT" means all ciphersuites are enabled, including the * low-security 40 bit ciphers. * * "NONE" means nothing is enabled. This disables even protocols and * compression methods. * * Special keywords are "!", "-" and "+". * "!" or "-" appended with an algorithm will remove this algorithm. * "+" appended with an algorithm will add this algorithm. * * Check the GnuTLS manual section "Priority strings" for detailed * information. * * Examples: * * "NONE:+VERS-TLS-ALL:+MAC-ALL:+RSA:+AES-128-CBC:+SIGN-ALL:+COMP-NULL" * * "NORMAL:-ARCFOUR-128" means normal ciphers except for ARCFOUR-128. * * "SECURE128:-VERS-SSL3.0:+COMP-DEFLATE" means that only secure ciphers are * enabled, SSL3.0 is disabled, and libz compression enabled. * * "NONE:+VERS-TLS-ALL:+AES-128-CBC:+RSA:+SHA1:+COMP-NULL:+SIGN-RSA-SHA1", * * "NONE:+VERS-TLS-ALL:+AES-128-CBC:+ECDHE-RSA:+SHA1:+COMP-NULL:+SIGN-RSA-SHA1:+CURVE-SECP256R1", * * "SECURE256:+SECURE128", * * Note that "NORMAL:%COMPAT" is the most compatible mode. * * Returns: On syntax error %GNUTLS_E_INVALID_REQUEST is returned, * %GNUTLS_E_SUCCESS on success, or an error code. **/ int gnutls_priority_init(gnutls_priority_t * priority_cache, const char *priorities, const char **err_pos) { char *broken_list[MAX_ELEMENTS]; int broken_list_size = 0, i = 0, j; char *darg = NULL; unsigned ikeyword_set = 0; int algo; rmadd_func *fn; bulk_rmadd_func *bulk_fn; *priority_cache = gnutls_calloc(1, sizeof(struct gnutls_priority_st)); if (*priority_cache == NULL) { gnutls_assert(); return GNUTLS_E_MEMORY_ERROR; } if (err_pos) *err_pos = priorities; /* for now unsafe renegotiation is default on everyone. To be removed * when we make it the default. */ (*priority_cache)->sr = SR_PARTIAL; (*priority_cache)->ssl3_record_version = 1; (*priority_cache)->max_empty_records = DEFAULT_MAX_EMPTY_RECORDS; if (priorities == NULL) priorities = LEVEL_NORMAL; darg = gnutls_strdup(priorities); if (darg == NULL) { gnutls_assert(); goto error; } break_comma_list(darg, broken_list, &broken_list_size, MAX_ELEMENTS, ':'); /* This is our default set of protocol version, certificate types and * compression methods. */ if (strcasecmp(broken_list[0], LEVEL_NONE) != 0) { _set_priority(&(*priority_cache)->protocol, protocol_priority); _set_priority(&(*priority_cache)->compression, comp_priority); _set_priority(&(*priority_cache)->cert_type, cert_type_priority_default); _set_priority(&(*priority_cache)->sign_algo, sign_priority_default); _set_priority(&(*priority_cache)->supported_ecc, supported_ecc_normal); i = 0; } else { ikeyword_set = 1; i = 1; } for (; i < broken_list_size; i++) { if (check_level(broken_list[i], *priority_cache, ikeyword_set) != 0) { ikeyword_set = 1; continue; } else if (broken_list[i][0] == '!' || broken_list[i][0] == '+' || broken_list[i][0] == '-') { if (broken_list[i][0] == '+') { fn = prio_add; bulk_fn = _add_priority; } else { fn = prio_remove; bulk_fn = _clear_priorities; } if (broken_list[i][0] == '+' && check_level(&broken_list[i][1], *priority_cache, 1) != 0) { continue; } else if ((algo = gnutls_mac_get_id(&broken_list[i][1])) != GNUTLS_MAC_UNKNOWN) fn(&(*priority_cache)->mac, algo); else if ((algo = gnutls_cipher_get_id(&broken_list[i][1])) != GNUTLS_CIPHER_UNKNOWN) fn(&(*priority_cache)->cipher, algo); else if ((algo = gnutls_kx_get_id(&broken_list[i][1])) != GNUTLS_KX_UNKNOWN) fn(&(*priority_cache)->kx, algo); else if (strncasecmp (&broken_list[i][1], "VERS-", 5) == 0) { if (strncasecmp (&broken_list[i][1], "VERS-TLS-ALL", 12) == 0) { bulk_fn(&(*priority_cache)-> protocol, protocol_priority); } else if (strncasecmp (&broken_list[i][1], "VERS-DTLS-ALL", 13) == 0) { bulk_fn(&(*priority_cache)-> protocol, dtls_protocol_priority); } else { if ((algo = gnutls_protocol_get_id (&broken_list[i][6])) != GNUTLS_VERSION_UNKNOWN) fn(&(*priority_cache)-> protocol, algo); else goto error; } } /* now check if the element is something like -ALGO */ else if (strncasecmp (&broken_list[i][1], "COMP-", 5) == 0) { if (strncasecmp (&broken_list[i][1], "COMP-ALL", 8) == 0) { bulk_fn(&(*priority_cache)-> compression, comp_priority); } else { if ((algo = gnutls_compression_get_id (&broken_list[i][6])) != GNUTLS_COMP_UNKNOWN) fn(&(*priority_cache)-> compression, algo); else goto error; } } /* now check if the element is something like -ALGO */ else if (strncasecmp (&broken_list[i][1], "CURVE-", 6) == 0) { if (strncasecmp (&broken_list[i][1], "CURVE-ALL", 9) == 0) { bulk_fn(&(*priority_cache)-> supported_ecc, supported_ecc_normal); } else { if ((algo = _gnutls_ecc_curve_get_id (&broken_list[i][7])) != GNUTLS_ECC_CURVE_INVALID) fn(&(*priority_cache)-> supported_ecc, algo); else goto error; } } /* now check if the element is something like -ALGO */ else if (strncasecmp (&broken_list[i][1], "CTYPE-", 6) == 0) { if (strncasecmp (&broken_list[i][1], "CTYPE-ALL", 9) == 0) { bulk_fn(&(*priority_cache)-> cert_type, cert_type_priority_all); } else { if ((algo = gnutls_certificate_type_get_id (&broken_list[i][7])) != GNUTLS_CRT_UNKNOWN) fn(&(*priority_cache)-> cert_type, algo); else goto error; } } /* now check if the element is something like -ALGO */ else if (strncasecmp (&broken_list[i][1], "SIGN-", 5) == 0) { if (strncasecmp (&broken_list[i][1], "SIGN-ALL", 8) == 0) { bulk_fn(&(*priority_cache)-> sign_algo, sign_priority_default); } else { if ((algo = gnutls_sign_get_id (&broken_list[i][6])) != GNUTLS_SIGN_UNKNOWN) fn(&(*priority_cache)-> sign_algo, algo); else goto error; } } else if (strncasecmp (&broken_list[i][1], "MAC-ALL", 7) == 0) { bulk_fn(&(*priority_cache)->mac, mac_priority_normal); } else if (strncasecmp (&broken_list[i][1], "CIPHER-ALL", 10) == 0) { bulk_fn(&(*priority_cache)->cipher, cipher_priority_normal); } else if (strncasecmp (&broken_list[i][1], "KX-ALL", 6) == 0) { bulk_fn(&(*priority_cache)->kx, kx_priority_secure); } else goto error; } else if (broken_list[i][0] == '%') { if (strcasecmp(&broken_list[i][1], "COMPAT") == 0) { ENABLE_COMPAT((*priority_cache)); } else if (strcasecmp(&broken_list[i][1], "DUMBFW") == 0) { (*priority_cache)->dumbfw = 1; } else if (strcasecmp (&broken_list[i][1], "NO_EXTENSIONS") == 0) { (*priority_cache)->no_extensions = 1; } else if (strcasecmp (&broken_list[i][1], "STATELESS_COMPRESSION") == 0) { (*priority_cache)->stateless_compression = 1; } else if (strcasecmp (&broken_list[i][1], "VERIFY_ALLOW_SIGN_RSA_MD5") == 0) { prio_add(&(*priority_cache)->sign_algo, GNUTLS_SIGN_RSA_MD5); (*priority_cache)-> additional_verify_flags |= GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD5; } else if (strcasecmp (&broken_list[i][1], "VERIFY_DISABLE_CRL_CHECKS") == 0) { (*priority_cache)-> additional_verify_flags |= GNUTLS_VERIFY_DISABLE_CRL_CHECKS; } else if (strcasecmp (&broken_list[i][1], "SSL3_RECORD_VERSION") == 0) (*priority_cache)->ssl3_record_version = 1; else if (strcasecmp(&broken_list[i][1], "LATEST_RECORD_VERSION") == 0) (*priority_cache)->ssl3_record_version = 0; else if (strcasecmp(&broken_list[i][1], "VERIFY_ALLOW_X509_V1_CA_CRT") == 0) (*priority_cache)-> additional_verify_flags |= GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT; else if (strcasecmp (&broken_list[i][1], "UNSAFE_RENEGOTIATION") == 0) { (*priority_cache)->sr = SR_UNSAFE; } else if (strcasecmp (&broken_list[i][1], "SAFE_RENEGOTIATION") == 0) { (*priority_cache)->sr = SR_SAFE; } else if (strcasecmp(&broken_list[i][1], "PARTIAL_RENEGOTIATION") == 0) { (*priority_cache)->sr = SR_PARTIAL; } else if (strcasecmp(&broken_list[i][1], "DISABLE_SAFE_RENEGOTIATION") == 0) { (*priority_cache)->sr = SR_DISABLED; } else if (strcasecmp(&broken_list[i][1], "SERVER_PRECEDENCE") == 0) { (*priority_cache)->server_precedence = 1; } else if (strcasecmp(&broken_list[i][1], "NEW_PADDING") == 0) { (*priority_cache)->new_record_padding = 1; } else goto error; } else goto error; } gnutls_free(darg); return 0; error: if (err_pos != NULL && i < broken_list_size) { *err_pos = priorities; for (j = 0; j < i; j++) { (*err_pos) += strlen(broken_list[j]) + 1; } } gnutls_free(darg); gnutls_free(*priority_cache); *priority_cache = NULL; return GNUTLS_E_INVALID_REQUEST; }
static int pkcs8_key_info(const gnutls_datum_t * raw_key, const struct pkcs_cipher_schema_st **p, struct pbkdf2_params *kdf_params, char **oid) { int result, len; char enc_oid[MAX_OID_SIZE*2]; int params_start, params_end, params_len; struct pbe_enc_params enc_params; schema_id schema; ASN1_TYPE pkcs8_asn = ASN1_TYPE_EMPTY; memset(&enc_params, 0, sizeof(enc_params)); result = check_for_decrypted(raw_key); if (result == 0) return GNUTLS_E_INVALID_REQUEST; if ((result = asn1_create_element(_gnutls_get_pkix(), "PKIX1.pkcs-8-EncryptedPrivateKeyInfo", &pkcs8_asn)) != ASN1_SUCCESS) { gnutls_assert(); result = _gnutls_asn2err(result); goto error; } result = _asn1_strict_der_decode(&pkcs8_asn, raw_key->data, raw_key->size, NULL); if (result != ASN1_SUCCESS) { gnutls_assert(); result = _gnutls_asn2err(result); goto error; } /* Check the encryption schema OID */ len = sizeof(enc_oid); result = asn1_read_value(pkcs8_asn, "encryptionAlgorithm.algorithm", enc_oid, &len); if (result != ASN1_SUCCESS) { gnutls_assert(); goto error; } if (oid) { *oid = gnutls_strdup(enc_oid); } if ((result = _gnutls_check_pkcs_cipher_schema(enc_oid)) < 0) { gnutls_assert(); goto error; } schema = result; /* Get the DER encoding of the parameters. */ result = asn1_der_decoding_startEnd(pkcs8_asn, raw_key->data, raw_key->size, "encryptionAlgorithm.parameters", ¶ms_start, ¶ms_end); if (result != ASN1_SUCCESS) { gnutls_assert(); result = _gnutls_asn2err(result); goto error; } params_len = params_end - params_start + 1; result = _gnutls_read_pkcs_schema_params(&schema, NULL, &raw_key->data[params_start], params_len, kdf_params, &enc_params); if (result < 0) { gnutls_assert(); if (oid && enc_params.pbes2_oid[0] != 0) { snprintf(enc_oid, sizeof(enc_oid), "%s/%s", *oid, enc_params.pbes2_oid); gnutls_free(*oid); *oid = gnutls_strdup(enc_oid); } goto error; } *p = _gnutls_pkcs_schema_get(schema); if (*p == NULL) { gnutls_assert(); result = GNUTLS_E_UNKNOWN_CIPHER_TYPE; goto error; } result = 0; error: asn1_delete_structure2(&pkcs8_asn, ASN1_DELETE_FLAG_ZEROIZE); return result; }