/** * tlsv1_client_deinit - Deinitialize TLSv1 client connection * @conn: TLSv1 client connection data from tlsv1_client_init() */ void tlsv1_client_deinit(struct tlsv1_client *conn) { crypto_public_key_free(conn->server_rsa_key); tlsv1_record_set_cipher_suite(&conn->rl, TLS_NULL_WITH_NULL_NULL); tlsv1_record_change_write_cipher(&conn->rl); tlsv1_record_change_read_cipher(&conn->rl); tls_verify_hash_free(&conn->verify); os_free(conn->client_hello_ext); tlsv1_client_free_dh(conn); tlsv1_cred_free(conn->cred); os_free(conn); }
static void tlsv1_server_clear_data(struct tlsv1_server *conn) { tlsv1_record_set_cipher_suite(&conn->rl, TLS_NULL_WITH_NULL_NULL); tlsv1_record_change_write_cipher(&conn->rl); tlsv1_record_change_read_cipher(&conn->rl); tls_verify_hash_free(&conn->verify); crypto_public_key_free(conn->client_rsa_key); conn->client_rsa_key = NULL; os_free(conn->session_ticket); conn->session_ticket = NULL; conn->session_ticket_len = 0; conn->use_session_ticket = 0; os_free(conn->dh_secret); conn->dh_secret = NULL; conn->dh_secret_len = 0; }
/** * tlsv1_client_shutdown - Shutdown TLS connection * @conn: TLSv1 client connection data from tlsv1_client_init() * Returns: 0 on success, -1 on failure */ int tlsv1_client_shutdown(struct tlsv1_client *conn) { conn->state = CLIENT_HELLO; if (tls_verify_hash_init(&conn->verify) < 0) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to re-initialize verify " "hash"); return -1; } tlsv1_record_set_cipher_suite(&conn->rl, TLS_NULL_WITH_NULL_NULL); tlsv1_record_change_write_cipher(&conn->rl); tlsv1_record_change_read_cipher(&conn->rl); conn->certificate_requested = 0; crypto_public_key_free(conn->server_rsa_key); conn->server_rsa_key = NULL; conn->session_resumed = 0; return 0; }
static int tls_process_certificate(struct tlsv1_server *conn, u8 ct, const u8 *in_data, size_t *in_len) { const u8 *pos, *end; size_t left, len, list_len, cert_len, idx; u8 type; struct x509_certificate *chain = NULL, *last = NULL, *cert; int reason; if (ct != TLS_CONTENT_TYPE_HANDSHAKE) { wpa_printf(MSG_DEBUG, "TLSv1: Expected Handshake; " "received content type 0x%x", ct); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_UNEXPECTED_MESSAGE); return -1; } pos = in_data; left = *in_len; if (left < 4) { wpa_printf(MSG_DEBUG, "TLSv1: Too short Certificate message " "(len=%lu)", (unsigned long) left); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); return -1; } type = *pos++; len = WPA_GET_BE24(pos); pos += 3; left -= 4; if (len > left) { wpa_printf(MSG_DEBUG, "TLSv1: Unexpected Certificate message " "length (len=%lu != left=%lu)", (unsigned long) len, (unsigned long) left); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); return -1; } if (type == TLS_HANDSHAKE_TYPE_CLIENT_KEY_EXCHANGE) { if (conn->verify_peer) { wpa_printf(MSG_DEBUG, "TLSv1: Client did not include " "Certificate"); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_UNEXPECTED_MESSAGE); return -1; } return tls_process_client_key_exchange(conn, ct, in_data, in_len); } if (type != TLS_HANDSHAKE_TYPE_CERTIFICATE) { wpa_printf(MSG_DEBUG, "TLSv1: Received unexpected handshake " "message %d (expected Certificate/" "ClientKeyExchange)", type); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_UNEXPECTED_MESSAGE); return -1; } wpa_printf(MSG_DEBUG, "TLSv1: Received Certificate (certificate_list len %lu)", (unsigned long) len); /* * opaque ASN.1Cert<2^24-1>; * * struct { * ASN.1Cert certificate_list<1..2^24-1>; * } Certificate; */ end = pos + len; if (end - pos < 3) { wpa_printf(MSG_DEBUG, "TLSv1: Too short Certificate " "(left=%lu)", (unsigned long) left); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); return -1; } list_len = WPA_GET_BE24(pos); pos += 3; if ((size_t) (end - pos) != list_len) { wpa_printf(MSG_DEBUG, "TLSv1: Unexpected certificate_list " "length (len=%lu left=%lu)", (unsigned long) list_len, (unsigned long) (end - pos)); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); return -1; } idx = 0; while (pos < end) { if (end - pos < 3) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to parse " "certificate_list"); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); x509_certificate_chain_free(chain); return -1; } cert_len = WPA_GET_BE24(pos); pos += 3; if ((size_t) (end - pos) < cert_len) { wpa_printf(MSG_DEBUG, "TLSv1: Unexpected certificate " "length (len=%lu left=%lu)", (unsigned long) cert_len, (unsigned long) (end - pos)); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_DECODE_ERROR); x509_certificate_chain_free(chain); return -1; } wpa_printf(MSG_DEBUG, "TLSv1: Certificate %lu (len %lu)", (unsigned long) idx, (unsigned long) cert_len); if (idx == 0) { crypto_public_key_free(conn->client_rsa_key); if (tls_parse_cert(pos, cert_len, &conn->client_rsa_key)) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to parse " "the certificate"); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_BAD_CERTIFICATE); x509_certificate_chain_free(chain); return -1; } } cert = x509_certificate_parse(pos, cert_len); if (cert == NULL) { wpa_printf(MSG_DEBUG, "TLSv1: Failed to parse " "the certificate"); tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, TLS_ALERT_BAD_CERTIFICATE); x509_certificate_chain_free(chain); return -1; } if (last == NULL) chain = cert; else last->next = cert; last = cert; idx++; pos += cert_len; } if (x509_certificate_chain_validate(conn->cred->trusted_certs, chain, &reason) < 0) { int tls_reason; wpa_printf(MSG_DEBUG, "TLSv1: Server certificate chain " "validation failed (reason=%d)", reason); switch (reason) { case X509_VALIDATE_BAD_CERTIFICATE: tls_reason = TLS_ALERT_BAD_CERTIFICATE; break; case X509_VALIDATE_UNSUPPORTED_CERTIFICATE: tls_reason = TLS_ALERT_UNSUPPORTED_CERTIFICATE; break; case X509_VALIDATE_CERTIFICATE_REVOKED: tls_reason = TLS_ALERT_CERTIFICATE_REVOKED; break; case X509_VALIDATE_CERTIFICATE_EXPIRED: tls_reason = TLS_ALERT_CERTIFICATE_EXPIRED; break; case X509_VALIDATE_CERTIFICATE_UNKNOWN: tls_reason = TLS_ALERT_CERTIFICATE_UNKNOWN; break; case X509_VALIDATE_UNKNOWN_CA: tls_reason = TLS_ALERT_UNKNOWN_CA; break; default: tls_reason = TLS_ALERT_BAD_CERTIFICATE; break; } tlsv1_server_alert(conn, TLS_ALERT_LEVEL_FATAL, tls_reason); x509_certificate_chain_free(chain); return -1; } x509_certificate_chain_free(chain); *in_len = end - in_data; conn->state = CLIENT_KEY_EXCHANGE; return 0; }
static int cavp_rsa_sig_ver(const char *fname) { FILE *f; int ret = 0; char buf[15000], *pos, *pos2; u8 msg[200], n[512], s[512], em[512], e[512]; size_t msg_len = 0, n_len = 0, s_len = 0, em_len, e_len = 0; size_t tmp_len; char sha_alg[20]; int ok = 0; printf("CAVP RSA SigVer test vectors from %s\n", fname); f = fopen(fname, "r"); if (f == NULL) { printf("%s does not exist - cannot validate CAVP RSA SigVer test vectors\n", fname); return 0; } while (fgets(buf, sizeof(buf), f)) { pos = os_strchr(buf, '='); if (pos == NULL) continue; pos2 = pos - 1; while (pos2 >= buf && *pos2 == ' ') *pos2-- = '\0'; *pos++ = '\0'; while (*pos == ' ') *pos++ = '\0'; pos2 = os_strchr(pos, '\r'); if (!pos2) pos2 = os_strchr(pos, '\n'); if (pos2) *pos2 = '\0'; else pos2 = pos + os_strlen(pos); if (os_strcmp(buf, "SHAAlg") == 0) { os_strlcpy(sha_alg, pos, sizeof(sha_alg)); } else if (os_strcmp(buf, "Msg") == 0) { tmp_len = os_strlen(pos); if (tmp_len > sizeof(msg) * 2) { printf("Too long Msg\n"); return -1; } msg_len = tmp_len / 2; if (hexstr2bin(pos, msg, msg_len) < 0) { printf("Invalid hex string '%s'\n", pos); ret++; break; } } else if (os_strcmp(buf, "n") == 0) { tmp_len = os_strlen(pos); if (tmp_len > sizeof(n) * 2) { printf("Too long n\n"); return -1; } n_len = tmp_len / 2; if (hexstr2bin(pos, n, n_len) < 0) { printf("Invalid hex string '%s'\n", pos); ret++; break; } } else if (os_strcmp(buf, "e") == 0) { tmp_len = os_strlen(pos); if (tmp_len > sizeof(e) * 2) { printf("Too long e\n"); return -1; } e_len = tmp_len / 2; if (hexstr2bin(pos, e, e_len) < 0) { printf("Invalid hex string '%s'\n", pos); ret++; break; } } else if (os_strcmp(buf, "S") == 0) { tmp_len = os_strlen(pos); if (tmp_len > sizeof(s) * 2) { printf("Too long S\n"); return -1; } s_len = tmp_len / 2; if (hexstr2bin(pos, s, s_len) < 0) { printf("Invalid hex string '%s'\n", pos); ret++; break; } } else if (os_strncmp(buf, "EM", 2) == 0) { tmp_len = os_strlen(pos); if (tmp_len > sizeof(em) * 2) return -1; em_len = tmp_len / 2; if (hexstr2bin(pos, em, em_len) < 0) { printf("Invalid hex string '%s'\n", pos); ret++; break; } } else if (os_strcmp(buf, "Result") == 0) { const u8 *addr[1]; size_t len[1]; struct crypto_public_key *pk; int res; u8 hash[32]; size_t hash_len; const struct asn1_oid *alg; addr[0] = msg; len[0] = msg_len; if (os_strcmp(sha_alg, "SHA1") == 0) { if (sha1_vector(1, addr, len, hash) < 0) return -1; hash_len = 20; alg = &asn1_sha1_oid; } else if (os_strcmp(sha_alg, "SHA256") == 0) { if (sha256_vector(1, addr, len, hash) < 0) return -1; hash_len = 32; alg = &asn1_sha256_oid; } else { continue; } printf("\nExpected result: %s\n", pos); wpa_hexdump(MSG_INFO, "Hash(Msg)", hash, hash_len); pk = crypto_public_key_import_parts(n, n_len, e, e_len); if (pk == NULL) { printf("Failed to import public key\n"); ret++; continue; } res = pkcs1_v15_sig_ver(pk, s, s_len, alg, hash, hash_len); crypto_public_key_free(pk); if ((*pos == 'F' && !res) || (*pos != 'F' && res)) { printf("FAIL\n"); ret++; continue; } printf("PASS\n"); ok++; } } fclose(f); if (ret) printf("Test case failed\n"); else printf("%d test vectors OK\n", ok); return ret; }