Mercurial > hg > nginx-quic
comparison src/http/ngx_http_request.c @ 7643:76e29ff31cd3 quic
AEAD routines, introduced ngx_quic_tls_open()/ngx_quic_tls_seal().
author | Sergey Kandaurov <pluknet@nginx.com> |
---|---|
date | Fri, 28 Feb 2020 13:09:52 +0300 |
parents | 8964cc6ecc4a |
children | a9ff4392ecde |
comparison
equal
deleted
inserted
replaced
7642:8964cc6ecc4a | 7643:76e29ff31cd3 |
---|---|
781 } | 781 } |
782 #endif | 782 #endif |
783 | 783 |
784 // initial secret | 784 // initial secret |
785 | 785 |
786 size_t is_len; | 786 size_t is_len; |
787 uint8_t is[SHA256_DIGEST_LENGTH]; | 787 uint8_t is[SHA256_DIGEST_LENGTH]; |
788 const EVP_MD *digest; | 788 const EVP_MD *digest; |
789 #ifdef OPENSSL_IS_BORINGSSL | 789 const ngx_aead_cipher_t *cipher; |
790 const EVP_AEAD *cipher; | |
791 #else | |
792 const EVP_CIPHER *cipher; | |
793 #endif | |
794 static const uint8_t salt[20] = | 790 static const uint8_t salt[20] = |
795 "\xc3\xee\xf7\x12\xc7\x2e\xbb\x5a\x11\xa7" | 791 "\xc3\xee\xf7\x12\xc7\x2e\xbb\x5a\x11\xa7" |
796 "\xd2\x43\x2b\xb4\x63\x65\xbe\xf9\xf5\x02"; | 792 "\xd2\x43\x2b\xb4\x63\x65\xbe\xf9\xf5\x02"; |
797 | 793 |
794 /* AEAD_AES_128_GCM prior to handshake, quic-tls-23#section-5.3 */ | |
795 | |
796 cipher = NGX_QUIC_INITIAL_CIPHER; | |
798 digest = EVP_sha256(); | 797 digest = EVP_sha256(); |
799 | |
800 /* AEAD_AES_128_GCM prior to handshake, quic-tls-23#section-5.3 */ | |
801 | |
802 #ifdef OPENSSL_IS_BORINGSSL | |
803 cipher = EVP_aead_aes_128_gcm(); | |
804 #else | |
805 cipher = EVP_aes_128_gcm(); | |
806 #endif | |
807 | 798 |
808 if (ngx_hkdf_extract(is, &is_len, digest, qc->dcid.data, qc->dcid.len, | 799 if (ngx_hkdf_extract(is, &is_len, digest, qc->dcid.data, qc->dcid.len, |
809 salt, sizeof(salt)) | 800 salt, sizeof(salt)) |
810 != NGX_OK) | 801 != NGX_OK) |
811 { | 802 { |
1177 } | 1168 } |
1178 #endif | 1169 #endif |
1179 | 1170 |
1180 // packet protection | 1171 // packet protection |
1181 | 1172 |
1182 ngx_str_t ciphertext; | 1173 ngx_str_t in; |
1183 ciphertext.data = b->pos; | 1174 in.data = b->pos; |
1184 ciphertext.len = plen - pnl; | 1175 in.len = plen - pnl; |
1185 | 1176 |
1186 ngx_str_t ad; | 1177 ngx_str_t ad; |
1187 ad.len = b->pos - b->start; | 1178 ad.len = b->pos - b->start; |
1188 ad.data = ngx_pnalloc(c->pool, ad.len); | 1179 ad.data = ngx_pnalloc(c->pool, ad.len); |
1189 if (ad.data == NULL) { | 1180 if (ad.data == NULL) { |
1208 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, rev->log, 0, | 1199 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, rev->log, 0, |
1209 "quic ad: %*s, len: %uz", m, buf, ad.len); | 1200 "quic ad: %*s, len: %uz", m, buf, ad.len); |
1210 } | 1201 } |
1211 #endif | 1202 #endif |
1212 | 1203 |
1213 uint8_t cleartext[1600]; | 1204 ngx_str_t out; |
1214 size_t cleartext_len; | 1205 |
1215 | 1206 if (ngx_quic_tls_open(c, cipher, &qc->client_in, &out, nonce, &in, &ad) |
1216 #ifdef OPENSSL_IS_BORINGSSL | 1207 != NGX_OK) |
1217 EVP_AEAD_CTX *aead = EVP_AEAD_CTX_new(cipher, | |
1218 qc->client_in.key.data, | |
1219 qc->client_in.key.len, | |
1220 EVP_AEAD_DEFAULT_TAG_LENGTH); | |
1221 if (aead == NULL) { | |
1222 ngx_ssl_error(NGX_LOG_INFO, rev->log, 0, "EVP_AEAD_CTX_new() failed"); | |
1223 ngx_http_close_connection(c); | |
1224 return; | |
1225 } | |
1226 | |
1227 if (EVP_AEAD_CTX_open(aead, cleartext, &cleartext_len, sizeof(cleartext), | |
1228 nonce, qc->client_in.iv.len, ciphertext.data, | |
1229 ciphertext.len, ad.data, ad.len) | |
1230 != 1) | |
1231 { | 1208 { |
1232 EVP_AEAD_CTX_free(aead); | 1209 ngx_http_close_connection(c); |
1233 ngx_ssl_error(NGX_LOG_INFO, rev->log, 0, | 1210 return; |
1234 "EVP_AEAD_CTX_open() failed"); | 1211 } |
1235 ngx_http_close_connection(c); | |
1236 return; | |
1237 } | |
1238 | |
1239 EVP_AEAD_CTX_free(aead); | |
1240 #else | |
1241 int len; | |
1242 u_char *tag; | |
1243 EVP_CIPHER_CTX *aead; | |
1244 | |
1245 aead = EVP_CIPHER_CTX_new(); | |
1246 if (aead == NULL) { | |
1247 ngx_ssl_error(NGX_LOG_INFO, rev->log, 0, "EVP_CIPHER_CTX_new() failed"); | |
1248 ngx_http_close_connection(c); | |
1249 return; | |
1250 } | |
1251 | |
1252 if (EVP_DecryptInit_ex(aead, cipher, NULL, NULL, NULL) != 1) { | |
1253 EVP_CIPHER_CTX_free(aead); | |
1254 ngx_ssl_error(NGX_LOG_INFO, rev->log, 0, "EVP_DecryptInit_ex() failed"); | |
1255 ngx_http_close_connection(c); | |
1256 return; | |
1257 } | |
1258 | |
1259 if (EVP_CIPHER_CTX_ctrl(aead, EVP_CTRL_GCM_SET_IVLEN, qc->client_in.iv.len, | |
1260 NULL) | |
1261 == 0) | |
1262 { | |
1263 EVP_CIPHER_CTX_free(aead); | |
1264 ngx_ssl_error(NGX_LOG_INFO, rev->log, 0, | |
1265 "EVP_CIPHER_CTX_ctrl(EVP_CTRL_GCM_SET_IVLEN) failed"); | |
1266 ngx_http_close_connection(c); | |
1267 return; | |
1268 } | |
1269 | |
1270 if (EVP_DecryptInit_ex(aead, NULL, NULL, qc->client_in.key.data, nonce) | |
1271 != 1) | |
1272 { | |
1273 EVP_CIPHER_CTX_free(aead); | |
1274 ngx_ssl_error(NGX_LOG_INFO, rev->log, 0, "EVP_DecryptInit_ex() failed"); | |
1275 ngx_http_close_connection(c); | |
1276 return; | |
1277 } | |
1278 | |
1279 if (EVP_DecryptUpdate(aead, NULL, &len, ad.data, ad.len) != 1) { | |
1280 EVP_CIPHER_CTX_free(aead); | |
1281 ngx_ssl_error(NGX_LOG_INFO, rev->log, 0, "EVP_DecryptUpdate() failed"); | |
1282 ngx_http_close_connection(c); | |
1283 return; | |
1284 } | |
1285 | |
1286 if (EVP_DecryptUpdate(aead, cleartext, &len, ciphertext.data, | |
1287 ciphertext.len - EVP_GCM_TLS_TAG_LEN) | |
1288 != 1) | |
1289 { | |
1290 EVP_CIPHER_CTX_free(aead); | |
1291 ngx_ssl_error(NGX_LOG_INFO, rev->log, 0, "EVP_DecryptUpdate() failed"); | |
1292 ngx_http_close_connection(c); | |
1293 return; | |
1294 } | |
1295 | |
1296 cleartext_len = len; | |
1297 tag = ciphertext.data + ciphertext.len - EVP_GCM_TLS_TAG_LEN; | |
1298 | |
1299 if (EVP_CIPHER_CTX_ctrl(aead, EVP_CTRL_GCM_SET_TAG, EVP_GCM_TLS_TAG_LEN, | |
1300 tag) | |
1301 == 0) | |
1302 { | |
1303 EVP_CIPHER_CTX_free(aead); | |
1304 ngx_ssl_error(NGX_LOG_INFO, rev->log, 0, | |
1305 "EVP_CIPHER_CTX_ctrl(EVP_CTRL_GCM_SET_TAG) failed"); | |
1306 ngx_http_close_connection(c); | |
1307 return; | |
1308 } | |
1309 | |
1310 if (EVP_DecryptFinal_ex(aead, cleartext + len, &len) <= 0) { | |
1311 EVP_CIPHER_CTX_free(aead); | |
1312 ngx_ssl_error(NGX_LOG_INFO, rev->log, 0, "EVP_DecryptFinal_ex failed"); | |
1313 ngx_http_close_connection(c); | |
1314 return; | |
1315 } | |
1316 | |
1317 cleartext_len += len; | |
1318 | |
1319 EVP_CIPHER_CTX_free(aead); | |
1320 #endif | |
1321 | 1212 |
1322 #if (NGX_DEBUG) | 1213 #if (NGX_DEBUG) |
1323 if (c->log->log_level & NGX_LOG_DEBUG_EVENT) { | 1214 if (c->log->log_level & NGX_LOG_DEBUG_EVENT) { |
1324 m = ngx_hex_dump(buf, cleartext, ngx_min(cleartext_len, 256)) - buf; | 1215 m = ngx_hex_dump(buf, out.data, ngx_min(out.len, 256)) - buf; |
1325 ngx_log_debug4(NGX_LOG_DEBUG_HTTP, rev->log, 0, | 1216 ngx_log_debug4(NGX_LOG_DEBUG_HTTP, rev->log, 0, |
1326 "quic packet payload: %*s%s, len: %uz", | 1217 "quic packet payload: %*s%s, len: %uz", |
1327 m, buf, m < 512 ? "" : "...", cleartext_len); | 1218 m, buf, m < 512 ? "" : "...", out.len); |
1328 } | 1219 } |
1329 #endif | 1220 #endif |
1330 | 1221 |
1331 if (cleartext[0] != 0x06) { | 1222 if (out.data[0] != 0x06) { |
1332 ngx_log_error(NGX_LOG_INFO, rev->log, 0, | 1223 ngx_log_error(NGX_LOG_INFO, rev->log, 0, |
1333 "unexpected frame in initial packet"); | 1224 "unexpected frame in initial packet"); |
1334 ngx_http_close_connection(c); | 1225 ngx_http_close_connection(c); |
1335 return; | 1226 return; |
1336 } | 1227 } |
1337 | 1228 |
1338 if (cleartext[1] != 0x00) { | 1229 if (out.data[1] != 0x00) { |
1339 ngx_log_error(NGX_LOG_INFO, rev->log, 0, | 1230 ngx_log_error(NGX_LOG_INFO, rev->log, 0, |
1340 "unexpected CRYPTO offset in initial packet"); | 1231 "unexpected CRYPTO offset in initial packet"); |
1341 ngx_http_close_connection(c); | 1232 ngx_http_close_connection(c); |
1342 return; | 1233 return; |
1343 } | 1234 } |
1344 | 1235 |
1345 uint8_t *crypto = &cleartext[2]; | 1236 uint8_t *crypto = &out.data[2]; |
1346 uint64_t crypto_len = ngx_quic_parse_int(&crypto); | 1237 uint64_t crypto_len = ngx_quic_parse_int(&crypto); |
1347 | 1238 |
1348 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, rev->log, 0, | 1239 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, rev->log, 0, |
1349 "quic initial packet CRYPTO length: %uL pp:%p:%p", | 1240 "quic initial packet CRYPTO length: %uL pp:%p:%p", |
1350 crypto_len, cleartext, crypto); | 1241 crypto_len, out.data, crypto); |
1351 | 1242 |
1352 sscf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_ssl_module); | 1243 sscf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_ssl_module); |
1353 | 1244 |
1354 if (ngx_ssl_create_connection(&sscf->ssl, c, NGX_SSL_BUFFER) | 1245 if (ngx_ssl_create_connection(&sscf->ssl, c, NGX_SSL_BUFFER) |
1355 != NGX_OK) | 1246 != NGX_OK) |
1463 } | 1354 } |
1464 | 1355 |
1465 m = ngx_hex_dump(buf, b, n) - buf; | 1356 m = ngx_hex_dump(buf, b, n) - buf; |
1466 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, rev->log, 0, | 1357 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, rev->log, 0, |
1467 "quic handshake handler: %*s, len: %uz", m, buf, n); | 1358 "quic handshake handler: %*s, len: %uz", m, buf, n); |
1468 | |
1469 /* XXX bug-for-bug compat - assuming initial ack in handshake pkt */ | |
1470 | 1359 |
1471 if ((p[0] & 0xf0) != 0xe0) { | 1360 if ((p[0] & 0xf0) != 0xe0) { |
1472 ngx_log_error(NGX_LOG_INFO, rev->log, 0, "invalid packet type"); | 1361 ngx_log_error(NGX_LOG_INFO, rev->log, 0, "invalid packet type"); |
1473 ngx_http_close_connection(c); | 1362 ngx_http_close_connection(c); |
1474 return; | 1363 return; |
1574 } | 1463 } |
1575 #endif | 1464 #endif |
1576 | 1465 |
1577 // packet protection | 1466 // packet protection |
1578 | 1467 |
1579 ngx_str_t ciphertext; | 1468 ngx_str_t in; |
1580 ciphertext.data = p; | 1469 in.data = p; |
1581 ciphertext.len = plen - pnl; | 1470 in.len = plen - pnl; |
1582 | 1471 |
1583 ngx_str_t ad; | 1472 ngx_str_t ad; |
1584 ad.len = p - b; | 1473 ad.len = p - b; |
1585 ad.data = ngx_pnalloc(c->pool, ad.len); | 1474 ad.data = ngx_pnalloc(c->pool, ad.len); |
1586 if (ad.data == NULL) { | 1475 if (ad.data == NULL) { |
1605 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, rev->log, 0, | 1494 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, rev->log, 0, |
1606 "quic ad: %*s, len: %uz", m, buf, ad.len); | 1495 "quic ad: %*s, len: %uz", m, buf, ad.len); |
1607 } | 1496 } |
1608 #endif | 1497 #endif |
1609 | 1498 |
1610 #ifdef OPENSSL_IS_BORINGSSL | 1499 const ngx_aead_cipher_t *cipher; |
1611 const EVP_AEAD *cipher; | |
1612 #else | |
1613 const EVP_CIPHER *cipher; | |
1614 #endif | |
1615 | 1500 |
1616 u_char *name = (u_char *) SSL_get_cipher(c->ssl->connection); | 1501 u_char *name = (u_char *) SSL_get_cipher(c->ssl->connection); |
1617 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, rev->log, 0, | 1502 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, rev->log, 0, |
1618 "quic ssl cipher: %s", name); | 1503 "quic ssl cipher: %s", name); |
1619 | 1504 |
1637 ngx_ssl_error(NGX_LOG_INFO, rev->log, 0, "unexpected cipher"); | 1522 ngx_ssl_error(NGX_LOG_INFO, rev->log, 0, "unexpected cipher"); |
1638 ngx_http_close_connection(c); | 1523 ngx_http_close_connection(c); |
1639 return; | 1524 return; |
1640 } | 1525 } |
1641 | 1526 |
1642 | 1527 ngx_str_t out; |
1643 uint8_t cleartext[1600]; | 1528 |
1644 size_t cleartext_len; | 1529 if (ngx_quic_tls_open(c, cipher, &qc->client_hs, &out, nonce, &in, &ad) |
1645 | 1530 != NGX_OK) |
1646 #ifdef OPENSSL_IS_BORINGSSL | |
1647 EVP_AEAD_CTX *aead = EVP_AEAD_CTX_new(cipher, | |
1648 qc->client_hs.key.data, | |
1649 qc->client_hs.key.len, | |
1650 EVP_AEAD_DEFAULT_TAG_LENGTH); | |
1651 if (aead == NULL) { | |
1652 ngx_ssl_error(NGX_LOG_INFO, rev->log, 0, "EVP_AEAD_CTX_new() failed"); | |
1653 ngx_http_close_connection(c); | |
1654 return; | |
1655 } | |
1656 | |
1657 if (EVP_AEAD_CTX_open(aead, cleartext, &cleartext_len, sizeof(cleartext), | |
1658 nonce, qc->client_hs.iv.len, ciphertext.data, | |
1659 ciphertext.len, ad.data, ad.len) | |
1660 != 1) | |
1661 { | 1531 { |
1662 EVP_AEAD_CTX_free(aead); | 1532 ngx_http_close_connection(c); |
1663 ngx_ssl_error(NGX_LOG_INFO, rev->log, 0, | 1533 return; |
1664 "EVP_AEAD_CTX_open() failed"); | 1534 } |
1665 ngx_http_close_connection(c); | |
1666 return; | |
1667 } | |
1668 | |
1669 EVP_AEAD_CTX_free(aead); | |
1670 #else | |
1671 int len; | |
1672 u_char *tag; | |
1673 EVP_CIPHER_CTX *aead; | |
1674 | |
1675 aead = EVP_CIPHER_CTX_new(); | |
1676 if (aead == NULL) { | |
1677 ngx_ssl_error(NGX_LOG_INFO, rev->log, 0, "EVP_CIPHER_CTX_new() failed"); | |
1678 ngx_http_close_connection(c); | |
1679 return; | |
1680 } | |
1681 | |
1682 if (EVP_DecryptInit_ex(aead, cipher, NULL, NULL, NULL) != 1) { | |
1683 EVP_CIPHER_CTX_free(aead); | |
1684 ngx_ssl_error(NGX_LOG_INFO, rev->log, 0, "EVP_DecryptInit_ex() failed"); | |
1685 ngx_http_close_connection(c); | |
1686 return; | |
1687 } | |
1688 | |
1689 if (EVP_CIPHER_CTX_ctrl(aead, EVP_CTRL_GCM_SET_IVLEN, qc->client_hs.iv.len, | |
1690 NULL) | |
1691 == 0) | |
1692 { | |
1693 EVP_CIPHER_CTX_free(aead); | |
1694 ngx_ssl_error(NGX_LOG_INFO, rev->log, 0, | |
1695 "EVP_CIPHER_CTX_ctrl(EVP_CTRL_GCM_SET_IVLEN) failed"); | |
1696 ngx_http_close_connection(c); | |
1697 return; | |
1698 } | |
1699 | |
1700 if (EVP_DecryptInit_ex(aead, NULL, NULL, qc->client_hs.key.data, nonce) | |
1701 != 1) | |
1702 { | |
1703 EVP_CIPHER_CTX_free(aead); | |
1704 ngx_ssl_error(NGX_LOG_INFO, rev->log, 0, "EVP_DecryptInit_ex() failed"); | |
1705 ngx_http_close_connection(c); | |
1706 return; | |
1707 } | |
1708 | |
1709 if (EVP_DecryptUpdate(aead, NULL, &len, ad.data, ad.len) != 1) { | |
1710 EVP_CIPHER_CTX_free(aead); | |
1711 ngx_ssl_error(NGX_LOG_INFO, rev->log, 0, "EVP_DecryptUpdate() failed"); | |
1712 ngx_http_close_connection(c); | |
1713 return; | |
1714 } | |
1715 | |
1716 if (EVP_DecryptUpdate(aead, cleartext, &len, ciphertext.data, | |
1717 ciphertext.len - EVP_GCM_TLS_TAG_LEN) | |
1718 != 1) | |
1719 { | |
1720 EVP_CIPHER_CTX_free(aead); | |
1721 ngx_ssl_error(NGX_LOG_INFO, rev->log, 0, "EVP_DecryptUpdate() failed"); | |
1722 ngx_http_close_connection(c); | |
1723 return; | |
1724 } | |
1725 | |
1726 cleartext_len = len; | |
1727 tag = ciphertext.data + ciphertext.len - EVP_GCM_TLS_TAG_LEN; | |
1728 | |
1729 if (EVP_CIPHER_CTX_ctrl(aead, EVP_CTRL_GCM_SET_TAG, EVP_GCM_TLS_TAG_LEN, | |
1730 tag) | |
1731 == 0) | |
1732 { | |
1733 EVP_CIPHER_CTX_free(aead); | |
1734 ngx_ssl_error(NGX_LOG_INFO, rev->log, 0, | |
1735 "EVP_CIPHER_CTX_ctrl(EVP_CTRL_GCM_SET_TAG) failed"); | |
1736 ngx_http_close_connection(c); | |
1737 return; | |
1738 } | |
1739 | |
1740 if (EVP_DecryptFinal_ex(aead, cleartext + len, &len) <= 0) { | |
1741 EVP_CIPHER_CTX_free(aead); | |
1742 ngx_ssl_error(NGX_LOG_INFO, rev->log, 0, "EVP_DecryptFinal_ex failed"); | |
1743 ngx_http_close_connection(c); | |
1744 return; | |
1745 } | |
1746 | |
1747 cleartext_len += len; | |
1748 | |
1749 EVP_CIPHER_CTX_free(aead); | |
1750 #endif | |
1751 | 1535 |
1752 #if (NGX_DEBUG) | 1536 #if (NGX_DEBUG) |
1753 if (c->log->log_level & NGX_LOG_DEBUG_EVENT) { | 1537 if (c->log->log_level & NGX_LOG_DEBUG_EVENT) { |
1754 m = ngx_hex_dump(buf, cleartext, ngx_min(cleartext_len, 256)) - buf; | 1538 m = ngx_hex_dump(buf, out.data, ngx_min(out.len, 256)) - buf; |
1755 ngx_log_debug4(NGX_LOG_DEBUG_HTTP, rev->log, 0, | 1539 ngx_log_debug4(NGX_LOG_DEBUG_HTTP, rev->log, 0, |
1756 "quic packet payload: %*s%s, len: %uz", | 1540 "quic packet payload: %*s%s, len: %uz", |
1757 m, buf, m < 512 ? "" : "...", cleartext_len); | 1541 m, buf, m < 512 ? "" : "...", out.len); |
1758 } | 1542 } |
1759 #endif | 1543 #endif |
1760 | 1544 |
1761 } | 1545 } |
1762 | 1546 |