mirror of
https://github.com/guanzhi/GmSSL.git
synced 2026-06-26 07:03:40 +08:00
remove old api
This commit is contained in:
@@ -135,6 +135,11 @@ int gcm_decrypt(const BLOCK_CIPHER_KEY *key, const uint8_t *iv, size_t ivlen,
|
||||
const uint8_t *aad, size_t aadlen, const uint8_t *in, size_t inlen,
|
||||
const uint8_t *tag, size_t taglen, uint8_t *out)
|
||||
{
|
||||
if (key->cipher == BLOCK_CIPHER_sm4()) {
|
||||
sm4_gcm_decrypt(&(key->u.sm4_key), iv, ivlen, aad, aadlen, in, inlen, tag, taglen, out);
|
||||
} else if (key->cipher == BLOCK_CIPHER_aes128()) {
|
||||
aes_gcm_decrypt(&(key->u.aes_key), iv, ivlen, aad, aadlen, in, inlen, tag, taglen, out);
|
||||
}
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
@@ -85,7 +85,7 @@ void gf128_print_bits(gf128_t a)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < 128; i++) {
|
||||
printf("%d", (int)(a % 2));
|
||||
printf("%d", a % 2);
|
||||
a >>= 1;
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
68
src/hmac.c
68
src/hmac.c
@@ -48,23 +48,13 @@
|
||||
|
||||
#include <string.h>
|
||||
#include <gmssl/hmac.h>
|
||||
#include <gmssl/error.h>
|
||||
|
||||
|
||||
#define IPAD 0x36
|
||||
#define OPAD 0x5C
|
||||
|
||||
|
||||
int hmac_ctx_init(HMAC_CTX *ctx)
|
||||
{
|
||||
memset(ctx, 0, sizeof(HMAC_CTX));
|
||||
return 1;
|
||||
}
|
||||
|
||||
void hmac_ctx_cleanup(HMAC_CTX *ctx)
|
||||
{
|
||||
memset(ctx, 0, sizeof(HMAC_CTX));
|
||||
}
|
||||
|
||||
int hmac_init(HMAC_CTX *ctx, const DIGEST *digest, const unsigned char *key, size_t keylen)
|
||||
{
|
||||
uint8_t i_key[DIGEST_MAX_BLOCK_SIZE] = {0};
|
||||
@@ -73,7 +63,8 @@ int hmac_init(HMAC_CTX *ctx, const DIGEST *digest, const unsigned char *key, siz
|
||||
int i;
|
||||
|
||||
if (!ctx || !digest || !key || !keylen) {
|
||||
return 0;
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
ctx->digest = digest;
|
||||
@@ -107,34 +98,45 @@ int hmac_init(HMAC_CTX *ctx, const DIGEST *digest, const unsigned char *key, siz
|
||||
int hmac_update(HMAC_CTX *ctx, const unsigned char *data, size_t datalen)
|
||||
{
|
||||
if (!ctx || (!data && datalen != 0)) {
|
||||
return 0;
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
return digest_update(&ctx->digest_ctx, data, datalen);
|
||||
if (digest_update(&ctx->digest_ctx, data, datalen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int hmac_finish(HMAC_CTX *ctx, unsigned char *mac, size_t *maclen)
|
||||
{
|
||||
int ret = 0;
|
||||
size_t i;
|
||||
size_t blocksize;
|
||||
|
||||
if (!digest_finish(&ctx->digest_ctx, mac, maclen)) {
|
||||
if (digest_finish(&ctx->digest_ctx, mac, maclen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
memcpy(&ctx->digest_ctx, &ctx->o_ctx, sizeof(DIGEST_CTX));
|
||||
if (!digest_update(&ctx->digest_ctx, mac, *maclen)
|
||||
|| !digest_finish(&ctx->digest_ctx, mac, maclen)) {
|
||||
goto end;
|
||||
if (digest_update(&ctx->digest_ctx, mac, *maclen) != 1
|
||||
|| digest_finish(&ctx->digest_ctx, mac, maclen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = 1;
|
||||
end:
|
||||
return ret;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int hmac_reset(HMAC_CTX *ctx)
|
||||
int hmac_finish_and_verify(HMAC_CTX *ctx, const uint8_t *mac, size_t maclen)
|
||||
{
|
||||
memcpy(&ctx->digest_ctx, &ctx->i_ctx, sizeof(DIGEST_CTX));
|
||||
uint8_t hmac[64];
|
||||
size_t hmaclen;
|
||||
|
||||
if (hmac_finish(ctx, hmac, &hmaclen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (maclen != hmaclen
|
||||
|| memcmp(hmac, mac, maclen) != 0) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -145,14 +147,14 @@ int hmac(const DIGEST *digest, const unsigned char *key, size_t keylen,
|
||||
int ret = 0;
|
||||
HMAC_CTX ctx;
|
||||
|
||||
if (!hmac_ctx_init(&ctx)
|
||||
|| !hmac_init(&ctx, digest, key, keylen)
|
||||
|| !hmac_update(&ctx, data, datalen)
|
||||
|| !hmac_finish(&ctx, mac, maclen)) {
|
||||
if (hmac_init(&ctx, digest, key, keylen) != 1
|
||||
|| hmac_update(&ctx, data, datalen) != 1
|
||||
|| hmac_finish(&ctx, mac, maclen) != 1) {
|
||||
goto end;
|
||||
}
|
||||
ret = 1;
|
||||
|
||||
end:
|
||||
hmac_ctx_cleanup(&ctx);
|
||||
memset(&ctx, 0, sizeof(ctx));
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -129,13 +129,14 @@ int pbkdf2_genkey(const DIGEST *digest,
|
||||
size_t outlen, uint8_t *out)
|
||||
{
|
||||
HMAC_CTX ctx;
|
||||
HMAC_CTX ctx_tmpl;
|
||||
uint32_t iter = 1;
|
||||
uint8_t iter_be[4];
|
||||
uint8_t tmp_block[64];
|
||||
uint8_t key_block[64];
|
||||
size_t len;
|
||||
|
||||
hmac_init(&ctx, digest, (uint8_t *)pass, passlen);
|
||||
hmac_init(&ctx_tmpl, digest, (uint8_t *)pass, passlen);
|
||||
|
||||
while (outlen > 0) {
|
||||
int i;
|
||||
@@ -143,16 +144,16 @@ int pbkdf2_genkey(const DIGEST *digest,
|
||||
PUTU32(iter_be, iter);
|
||||
iter++;
|
||||
|
||||
ctx = ctx_tmpl;
|
||||
hmac_update(&ctx, salt, saltlen);
|
||||
hmac_update(&ctx, iter_be, sizeof(iter_be));
|
||||
hmac_finish(&ctx, tmp_block, &len);
|
||||
hmac_reset(&ctx);
|
||||
memcpy(key_block, tmp_block, len);
|
||||
|
||||
for (i = 1; i < count; i++) {
|
||||
ctx = ctx_tmpl;
|
||||
hmac_update(&ctx, tmp_block, len);
|
||||
hmac_finish(&ctx, tmp_block, &len);
|
||||
hmac_reset(&ctx);
|
||||
memxor(key_block, tmp_block, len);
|
||||
}
|
||||
|
||||
|
||||
@@ -67,7 +67,7 @@ void sm4_cbc_decrypt(const SM4_KEY *key, const uint8_t iv[16],
|
||||
const uint8_t *in, size_t nblocks, uint8_t *out)
|
||||
{
|
||||
while (nblocks--) {
|
||||
sm4_decrypt(key, in, out);
|
||||
sm4_encrypt(key, in, out);
|
||||
memxor(out, iv, 16);
|
||||
iv = in;
|
||||
in += 16;
|
||||
|
||||
@@ -83,7 +83,7 @@ static uint32_t CK[32] = {
|
||||
x4 = x0 ^ L32_(x4); \
|
||||
*(rk + 31 - i) = x4
|
||||
|
||||
void sm4_set_encrypt_key(SM4_KEY *key, const unsigned char user_key[16])
|
||||
void sm4_set_encrypt_key(SM4_KEY *key, const uint8_t user_key[16])
|
||||
{
|
||||
uint32_t *rk = key->rk;
|
||||
uint32_t x0, x1, x2, x3, x4;
|
||||
@@ -100,7 +100,7 @@ void sm4_set_encrypt_key(SM4_KEY *key, const unsigned char user_key[16])
|
||||
x0 = x1 = x2 = x3 = x4 = 0;
|
||||
}
|
||||
|
||||
void sm4_set_decrypt_key(SM4_KEY *key, const unsigned char user_key[16])
|
||||
void sm4_set_decrypt_key(SM4_KEY *key, const uint8_t user_key[16])
|
||||
{
|
||||
uint32_t *rk = key->rk;
|
||||
uint32_t x0, x1, x2, x3, x4;
|
||||
|
||||
224
src/tls.c
224
src/tls.c
@@ -322,7 +322,118 @@ int tls_record_length(const uint8_t *record)
|
||||
}
|
||||
|
||||
|
||||
int tls_cbc_encrypt(const SM3_HMAC_CTX *inited_hmac_ctx, const SM4_KEY *enc_key,
|
||||
const uint8_t seq_num[8], const uint8_t header[5],
|
||||
const uint8_t *in, size_t inlen, uint8_t *out, size_t *outlen)
|
||||
{
|
||||
SM3_HMAC_CTX hmac_ctx;
|
||||
uint8_t last_blocks[32 + 16] = {0};
|
||||
uint8_t *mac, *padding, *iv;
|
||||
int rem, padding_len;
|
||||
int i;
|
||||
|
||||
if (!inited_hmac_ctx || !enc_key || !seq_num || !header || (!in && inlen) || !out || !outlen) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (inlen > (1 << 14)) {
|
||||
error_print("invalid tls record data length %zu\n", inlen);
|
||||
return -1;
|
||||
}
|
||||
|
||||
rem = (inlen + 32) % 16;
|
||||
memcpy(last_blocks, in + inlen - rem, rem);
|
||||
mac = last_blocks + rem;
|
||||
|
||||
memcpy(&hmac_ctx, inited_hmac_ctx, sizeof(SM3_HMAC_CTX));
|
||||
sm3_hmac_update(&hmac_ctx, seq_num, 8);
|
||||
sm3_hmac_update(&hmac_ctx, header, 5);
|
||||
sm3_hmac_update(&hmac_ctx, in, inlen);
|
||||
sm3_hmac_finish(&hmac_ctx, mac);
|
||||
|
||||
padding = mac + 32;
|
||||
padding_len = 16 - rem - 1;
|
||||
for (i = 0; i <= padding_len; i++) {
|
||||
padding[i] = padding_len;
|
||||
}
|
||||
|
||||
iv = out;
|
||||
if (rand_bytes(iv, 16) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
out += 16;
|
||||
|
||||
if (inlen >= 16) {
|
||||
sm4_cbc_encrypt(enc_key, iv, in, inlen/16, out);
|
||||
out += inlen - rem;
|
||||
iv = out - 16;
|
||||
}
|
||||
sm4_cbc_encrypt(enc_key, iv, last_blocks, sizeof(last_blocks)/16, out);
|
||||
*outlen = 16 + inlen - rem + sizeof(last_blocks);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tls_cbc_decrypt(const SM3_HMAC_CTX *inited_hmac_ctx, const SM4_KEY *dec_key,
|
||||
const uint8_t seq_num[8], const uint8_t enced_header[5],
|
||||
const uint8_t *in, size_t inlen, uint8_t *out, size_t *outlen)
|
||||
{
|
||||
SM3_HMAC_CTX hmac_ctx;
|
||||
const uint8_t *iv;
|
||||
const uint8_t *padding;
|
||||
const uint8_t *mac;
|
||||
uint8_t header[5];
|
||||
int padding_len;
|
||||
int i;
|
||||
|
||||
if (!inited_hmac_ctx || !dec_key || !seq_num || !enced_header || !in || !inlen || !out || !outlen) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (inlen % 16
|
||||
|| inlen < (16 + 0 + 32 + 16) // iv + data + mac + padding
|
||||
|| inlen > (16 + (1<<14) + 32 + 256)) {
|
||||
error_print("invalid tls cbc ciphertext length %zu\n", inlen);
|
||||
return -1;
|
||||
}
|
||||
|
||||
iv = in;
|
||||
in += 16;
|
||||
inlen -= 16;
|
||||
|
||||
sm4_cbc_decrypt(dec_key, iv, in, inlen/16, out);
|
||||
|
||||
padding_len = out[inlen - 1];
|
||||
padding = out + inlen - padding_len - 1;
|
||||
if (padding < out + 32) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
for (i = 0; i < padding_len; i++) {
|
||||
if (padding[i] != padding_len) {
|
||||
error_print("tls ciphertext cbc-padding check failure");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
*outlen = inlen - 32 - padding_len - 1;
|
||||
header[0] = enced_header[0];
|
||||
header[1] = enced_header[1];
|
||||
header[2] = enced_header[2];
|
||||
header[3] = (*outlen) >> 8;
|
||||
header[4] = (*outlen);
|
||||
mac = padding - 32;
|
||||
|
||||
memcpy(&hmac_ctx, inited_hmac_ctx, sizeof(SM3_HMAC_CTX));
|
||||
sm3_hmac_update(&hmac_ctx, seq_num, 8);
|
||||
sm3_hmac_update(&hmac_ctx, header, 5);
|
||||
sm3_hmac_update(&hmac_ctx, out, *outlen);
|
||||
if (sm3_hmac_finish_and_verify(&hmac_ctx, mac) != 1) {
|
||||
error_print("tls ciphertext mac check failure");
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
// 这个函数应该是处理的,这个函数是不应该用的,通常我们在加密的时候,header ,明文数据是分离的,但是输出的record是一个
|
||||
int tls_record_encrypt(const SM3_HMAC_CTX *hmac_ctx, const SM4_KEY *cbc_key,
|
||||
@@ -378,6 +489,62 @@ int tls_random_generate(uint8_t random[32])
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tls_prf(const uint8_t *secret, size_t secretlen, const char *label,
|
||||
const uint8_t *seed, size_t seedlen,
|
||||
const uint8_t *more, size_t morelen,
|
||||
size_t outlen, uint8_t *out)
|
||||
{
|
||||
SM3_HMAC_CTX inited_hmac_ctx;
|
||||
SM3_HMAC_CTX hmac_ctx;
|
||||
uint8_t A[32];
|
||||
uint8_t hmac[32];
|
||||
size_t len;
|
||||
|
||||
if (!secret || !secretlen || !label || !seed || !seedlen
|
||||
|| (!more && morelen) || !outlen || !out) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
sm3_hmac_init(&inited_hmac_ctx, secret, secretlen);
|
||||
|
||||
memcpy(&hmac_ctx, &inited_hmac_ctx, sizeof(SM3_HMAC_CTX));
|
||||
sm3_hmac_update(&hmac_ctx, (uint8_t *)label, strlen(label));
|
||||
sm3_hmac_update(&hmac_ctx, seed, seedlen);
|
||||
sm3_hmac_update(&hmac_ctx, more, morelen);
|
||||
sm3_hmac_finish(&hmac_ctx, A);
|
||||
|
||||
memcpy(&hmac_ctx, &inited_hmac_ctx, sizeof(SM3_HMAC_CTX));
|
||||
sm3_hmac_update(&hmac_ctx, A, sizeof(A));
|
||||
sm3_hmac_update(&hmac_ctx, (uint8_t *)label, strlen(label));
|
||||
sm3_hmac_update(&hmac_ctx, seed, seedlen);
|
||||
sm3_hmac_update(&hmac_ctx, more, morelen);
|
||||
sm3_hmac_finish(&hmac_ctx, hmac);
|
||||
|
||||
len = outlen < sizeof(hmac) ? outlen : sizeof(hmac);
|
||||
memcpy(out, hmac, len);
|
||||
out += len;
|
||||
outlen -= len;
|
||||
|
||||
while (outlen) {
|
||||
memcpy(&hmac_ctx, &inited_hmac_ctx, sizeof(SM3_HMAC_CTX));
|
||||
sm3_hmac_update(&hmac_ctx, A, sizeof(A));
|
||||
sm3_hmac_finish(&hmac_ctx, A);
|
||||
|
||||
memcpy(&hmac_ctx, &inited_hmac_ctx, sizeof(SM3_HMAC_CTX));
|
||||
sm3_hmac_update(&hmac_ctx, A, sizeof(A));
|
||||
sm3_hmac_update(&hmac_ctx, (uint8_t *)label, strlen(label));
|
||||
sm3_hmac_update(&hmac_ctx, seed, seedlen);
|
||||
sm3_hmac_update(&hmac_ctx, more, morelen);
|
||||
sm3_hmac_finish(&hmac_ctx, hmac);
|
||||
|
||||
len = outlen < sizeof(hmac) ? outlen : sizeof(hmac);
|
||||
memcpy(out, hmac, len);
|
||||
out += len;
|
||||
outlen -= len;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tls_pre_master_secret_generate(uint8_t pre_master_secret[48], int version)
|
||||
{
|
||||
@@ -396,6 +563,63 @@ int tls_pre_master_secret_generate(uint8_t pre_master_secret[48], int version)
|
||||
|
||||
|
||||
|
||||
int tls_sign_server_ecdh_params(const SM2_KEY *server_sign_key,
|
||||
const uint8_t client_random[32], const uint8_t server_random[32],
|
||||
int curve, const SM2_POINT *point, uint8_t *sig, size_t *siglen)
|
||||
{
|
||||
uint8_t server_ecdh_params[69];
|
||||
SM2_SIGN_CTX sign_ctx;
|
||||
|
||||
if (!server_sign_key || !client_random || !server_random
|
||||
|| curve != TLS_curve_sm2p256v1 || !point || !sig || !siglen) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
server_ecdh_params[0] = TLS_curve_type_named_curve;
|
||||
server_ecdh_params[1] = curve >> 8;
|
||||
server_ecdh_params[2] = curve;
|
||||
server_ecdh_params[3] = 65;
|
||||
sm2_point_to_uncompressed_octets(point, server_ecdh_params + 4);
|
||||
|
||||
sm2_sign_init(&sign_ctx, server_sign_key, SM2_DEFAULT_ID);
|
||||
sm2_sign_update(&sign_ctx, client_random, 32);
|
||||
sm2_sign_update(&sign_ctx, server_random, 32);
|
||||
sm2_sign_update(&sign_ctx, server_ecdh_params, 69);
|
||||
sm2_sign_finish(&sign_ctx, sig, siglen);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tls_verify_server_ecdh_params(const SM2_KEY *server_sign_key,
|
||||
const uint8_t client_random[32], const uint8_t server_random[32],
|
||||
int curve, const SM2_POINT *point, const uint8_t *sig, size_t siglen)
|
||||
{
|
||||
int ret;
|
||||
uint8_t server_ecdh_params[69];
|
||||
SM2_SIGN_CTX verify_ctx;
|
||||
|
||||
if (!server_sign_key || !client_random || !server_random
|
||||
|| curve != TLS_curve_sm2p256v1 || !point || !sig || !siglen
|
||||
|| siglen > TLS_MAX_SIGNATURE_SIZE) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
server_ecdh_params[0] = TLS_curve_type_named_curve;
|
||||
server_ecdh_params[1] = curve >> 8;
|
||||
server_ecdh_params[2] = curve;
|
||||
server_ecdh_params[3] = 65;
|
||||
sm2_point_to_uncompressed_octets(point, server_ecdh_params + 4);
|
||||
|
||||
sm2_verify_init(&verify_ctx, server_sign_key, SM2_DEFAULT_ID);
|
||||
sm2_verify_update(&verify_ctx, client_random, 32);
|
||||
sm2_verify_update(&verify_ctx, server_random, 32);
|
||||
sm2_verify_update(&verify_ctx, server_ecdh_params, 69);
|
||||
ret = sm2_verify_finish(&verify_ctx, sig, siglen);
|
||||
if (ret != 1) error_print();
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// handshakes
|
||||
|
||||
532
src/tls13.c
532
src/tls13.c
@@ -65,45 +65,66 @@
|
||||
#include <gmssl/pem.h>
|
||||
#include <gmssl/tls.h>
|
||||
#include <gmssl/digest.h>
|
||||
#include <gmssl/block_cipher.h>
|
||||
#include <gmssl/gcm.h>
|
||||
#include <gmssl/hmac.h>
|
||||
#include <gmssl/hkdf.h>
|
||||
#include "mem.h"
|
||||
|
||||
|
||||
int tls13_gcm_encrypt(const BLOCK_CIPHER_KEY *enc_key,
|
||||
const uint8_t iv[12], size_t padding_len,
|
||||
|
||||
/*
|
||||
struct {
|
||||
opaque content[TLSPlaintext.length];
|
||||
ContentType type;
|
||||
uint8 zeros[length_of_padding];
|
||||
} TLSInnerPlaintext;
|
||||
|
||||
struct {
|
||||
ContentType opaque_type = application_data; // 23
|
||||
ProtocolVersion legacy_record_version = 0x0303; // TLS v1.2
|
||||
uint16 length;
|
||||
opaque encrypted_record[TLSCiphertext.length];
|
||||
} TLSCiphertext;
|
||||
*/
|
||||
int tls13_gcm_encrypt(const BLOCK_CIPHER_KEY *key, const uint8_t iv[12],
|
||||
const uint8_t seq_num[8], int record_type,
|
||||
const uint8_t *in, size_t inlen, uint8_t *out, size_t *outlen)
|
||||
const uint8_t *in, size_t inlen, size_t padding_len, // TLSInnerPlaintext.content
|
||||
uint8_t *out, size_t *outlen) // TLSCiphertext.encrypted_record
|
||||
{
|
||||
uint8_t nonce[12];
|
||||
uint8_t *mbuf = malloc(inlen + 256);
|
||||
uint8_t aad[5];
|
||||
uint8_t *gmac;
|
||||
uint8_t *mbuf = malloc(inlen + 256); // FIXME: update gcm_encrypt API
|
||||
size_t mlen, clen;
|
||||
|
||||
// nonce = (zeros|seq_num) xor (iv)
|
||||
nonce[0] = nonce[1] = nonce[2] = 0;
|
||||
memcpy(nonce + 3, seq_num, 8);
|
||||
gmssl_memxor(nonce, nonce, iv, 12);
|
||||
|
||||
// TLSInnerPlaintext
|
||||
memcpy(mbuf, in, inlen);
|
||||
mbuf[inlen] = record_type;
|
||||
memset(mbuf + inlen + 1, 0, padding_len);
|
||||
mlen = inlen + 1 + padding_len;
|
||||
clen = mlen + 16;
|
||||
clen = mlen + GHASH_SIZE;
|
||||
|
||||
// aad = TLSCiphertext header
|
||||
aad[0] = TLS_record_application_data;
|
||||
aad[1] = 3;
|
||||
aad[2] = 3;
|
||||
aad[1] = TLS_version_tls12_major;
|
||||
aad[2] = TLS_version_tls12_minor;
|
||||
aad[3] = clen >> 8;
|
||||
aad[4] = clen;
|
||||
|
||||
gmac = out + mlen;
|
||||
gcm_encrypt(enc_key, nonce, sizeof(nonce), aad, sizeof(aad), mbuf, mlen, out, 16, gmac);
|
||||
if (gcm_encrypt(key, nonce, sizeof(nonce), aad, sizeof(aad), mbuf, mlen, out, 16, gmac) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tls13_gcm_decrypt(const BLOCK_CIPHER_KEY *sm4_key, const uint8_t iv[12],
|
||||
int tls13_gcm_decrypt(const BLOCK_CIPHER_KEY *key, const uint8_t iv[12],
|
||||
const uint8_t seq_num[8], const uint8_t *in, size_t inlen,
|
||||
int *record_type, uint8_t *out, size_t *outlen)
|
||||
{
|
||||
@@ -113,62 +134,335 @@ int tls13_gcm_decrypt(const BLOCK_CIPHER_KEY *sm4_key, const uint8_t iv[12],
|
||||
const uint8_t *gmac;
|
||||
size_t i;
|
||||
|
||||
// nonce = (zeros|seq_num) xor (iv)
|
||||
nonce[0] = nonce[1] = nonce[2] = 0;
|
||||
memcpy(nonce + 3, seq_num, 8);
|
||||
gmssl_memxor(nonce, nonce, iv, 12);
|
||||
|
||||
// aad = TLSCiphertext header
|
||||
aad[0] = TLS_record_application_data;
|
||||
aad[1] = 3;
|
||||
aad[2] = 3;
|
||||
aad[1] = TLS_version_tls12_major;
|
||||
aad[2] = TLS_version_tls12_minor;
|
||||
aad[3] = inlen >> 8;
|
||||
aad[4] = inlen;
|
||||
|
||||
mlen = inlen - 16;
|
||||
|
||||
if (inlen < GHASH_SIZE) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
mlen = inlen - GHASH_SIZE;
|
||||
gmac = in + mlen;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int tls13_record_encrypt(const BLOCK_CIPHER_KEY *key, const uint8_t iv[12],
|
||||
const uint8_t seq_num[8], const uint8_t *in, size_t inlen, size_t padding_len,
|
||||
uint8_t *out, size_t *outlen)
|
||||
{
|
||||
if (tls13_gcm_encrypt(key, iv, padding_len,
|
||||
seq_num, in[0], in + 5, inlen - 5, out + 5, outlen) != 1) {
|
||||
if (gcm_decrypt(key, iv, 12, aad, 5, in, mlen, gmac, GHASH_SIZE, out) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
out[0] = TLS_record_application_data;
|
||||
out[1] = in[1];
|
||||
out[2] = in[2];
|
||||
out[3] = (*outlen) >> 8;
|
||||
out[4] = (*outlen);
|
||||
(*outlen) += 5;
|
||||
// remove padding, get record_type
|
||||
*record_type = 0;
|
||||
while (mlen--) {
|
||||
if (out[mlen] != 0) {
|
||||
*record_type = out[mlen];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!tls_record_type_name(*record_type)) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tls13_record_encrypt(const BLOCK_CIPHER_KEY *key, const uint8_t iv[12],
|
||||
const uint8_t seq_num[8], const uint8_t *record, size_t recordlen, size_t padding_len,
|
||||
uint8_t *enced_record, size_t *enced_recordlen)
|
||||
{
|
||||
if (tls13_gcm_encrypt(key, iv,
|
||||
seq_num, record[0], record + 5, recordlen - 5, padding_len,
|
||||
enced_record + 5, enced_recordlen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
enced_record[0] = TLS_record_application_data;
|
||||
enced_record[1] = TLS_version_tls12_major;
|
||||
enced_record[2] = TLS_version_tls12_minor;
|
||||
enced_record[3] = (*enced_recordlen) >> 8;
|
||||
enced_record[4] = (*enced_recordlen);
|
||||
|
||||
(*enced_recordlen) += 5;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tls13_record_decrypt(const BLOCK_CIPHER_KEY *key, const uint8_t iv[12],
|
||||
const uint8_t seq_num[8], const uint8_t *in, size_t inlen,
|
||||
uint8_t *out, size_t *outlen)
|
||||
const uint8_t seq_num[8], const uint8_t *enced_record, size_t enced_recordlen,
|
||||
uint8_t *record, size_t *recordlen)
|
||||
{
|
||||
int record_type;
|
||||
|
||||
if (tls13_gcm_decrypt(key, iv, seq_num, in + 5, inlen - 5,
|
||||
&record_type, out + 5, outlen) != 1) {
|
||||
if (tls13_gcm_decrypt(key, iv,
|
||||
seq_num, enced_record + 5, enced_recordlen - 5,
|
||||
&record_type, record + 5, recordlen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
record[0] = record_type;
|
||||
record[1] = TLS_version_tls12_major;
|
||||
record[2] = TLS_version_tls12_minor;
|
||||
record[3] = (*recordlen) >> 8;
|
||||
record[4] = (*recordlen);
|
||||
|
||||
(*recordlen) += 5;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tls13_send(TLS_CONNECT *conn, const uint8_t *data, size_t datalen, size_t padding_len)
|
||||
{
|
||||
const BLOCK_CIPHER_KEY *key;
|
||||
const uint8_t *iv;
|
||||
uint8_t *seq_num;
|
||||
uint8_t *record = conn->record;
|
||||
size_t recordlen;
|
||||
|
||||
tls_trace("<<<< [ApplicationData]\n");
|
||||
|
||||
if (conn->is_client) {
|
||||
key = &conn->client_write_key;
|
||||
iv = conn->client_write_iv;
|
||||
seq_num = conn->client_seq_num;
|
||||
} else {
|
||||
key = &conn->server_write_key;
|
||||
iv = conn->server_write_iv;
|
||||
seq_num = conn->server_seq_num;
|
||||
}
|
||||
|
||||
if (tls13_gcm_encrypt(key, iv,
|
||||
seq_num, TLS_record_application_data, data, datalen, padding_len,
|
||||
record + 5, &recordlen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
out[0] = record_type;
|
||||
out[1] = in[1];
|
||||
out[2] = in[2];
|
||||
out[3] = (*outlen) >> 8;
|
||||
out[4] = (*outlen);
|
||||
record[0] = TLS_record_application_data;
|
||||
record[1] = TLS_version_tls12 >> 8;
|
||||
record[2] = TLS_version_tls12 & 0xff;
|
||||
record[3] = recordlen >> 8;
|
||||
record[4] = recordlen;
|
||||
recordlen += 5;
|
||||
|
||||
tls_record_send(record, recordlen, conn->sock);
|
||||
tls_seq_num_incr(seq_num);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tls13_recv(TLS_CONNECT *conn, uint8_t *data, size_t *datalen)
|
||||
{
|
||||
int record_type;
|
||||
uint8_t *record = conn->record;
|
||||
size_t recordlen;
|
||||
const BLOCK_CIPHER_KEY *key;
|
||||
const uint8_t *iv;
|
||||
uint8_t *seq_num;
|
||||
|
||||
|
||||
tls_trace(">>>> [ApplicationData]\n");
|
||||
|
||||
if (conn->is_client) {
|
||||
key = &conn->client_write_key;
|
||||
iv = conn->client_write_iv;
|
||||
seq_num = conn->client_seq_num;
|
||||
} else {
|
||||
key = &conn->server_write_key;
|
||||
iv = conn->server_write_iv;
|
||||
seq_num = conn->server_seq_num;
|
||||
}
|
||||
|
||||
if (tls12_record_recv(record, &recordlen, conn->sock) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (record[0] != TLS_record_application_data) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (tls13_gcm_decrypt(key, iv,
|
||||
seq_num, record + 5, recordlen - 5,
|
||||
&record_type, data, datalen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
tls_seq_num_incr(seq_num);
|
||||
|
||||
if (record_type != TLS_record_application_data) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
HKDF-Expand-Label(Secret, Label, Context, Length) =
|
||||
HKDF-Expand(Secret, HkdfLabel, Length);
|
||||
|
||||
HkdfLabel = struct {
|
||||
uint16 length = Length;
|
||||
opaque label<7..255> = "tls13 " + Label;
|
||||
opaque context<0..255> = Context; }
|
||||
|
||||
Derive-Secret(Secret, Label, Messages) =
|
||||
HKDF-Expand-Label(Secret, Label, Hash(Messages), Hash.length)
|
||||
|
||||
*/
|
||||
|
||||
int tls13_hkdf_extract(const DIGEST *digest, const uint8_t salt[32], const uint8_t in[32], uint8_t out[32])
|
||||
{
|
||||
size_t dgstlen;
|
||||
if (hkdf_extract(digest, salt, 32, in, 32, out, &dgstlen) != 1
|
||||
|| dgstlen != 32) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tls13_hkdf_expand_label(const DIGEST *digest, const uint8_t secret[32],
|
||||
const char *label, const uint8_t *context, size_t context_len,
|
||||
size_t outlen, uint8_t *out)
|
||||
{
|
||||
uint8_t label_len;
|
||||
uint8_t hkdf_label[2 + 256 + 256];
|
||||
uint8_t *p = hkdf_label;
|
||||
size_t hkdf_label_len = 0;
|
||||
|
||||
label_len = strlen("tls13") + strlen(label);
|
||||
tls_uint16_to_bytes((uint16_t)outlen, &p, &hkdf_label_len);
|
||||
tls_uint8_to_bytes(label_len, &p, &hkdf_label_len);
|
||||
tls_array_to_bytes((uint8_t *)"tls13", strlen("tls13"), &p, &hkdf_label_len);
|
||||
tls_array_to_bytes((uint8_t *)label, strlen(label), &p, &hkdf_label_len);
|
||||
tls_uint8array_to_bytes(context, context_len, &p, &hkdf_label_len);
|
||||
|
||||
hkdf_expand(digest, secret, 32, hkdf_label, hkdf_label_len, outlen, out);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tls13_derive_secret(const uint8_t secret[32], const char *label, const DIGEST_CTX *dgst_ctx, uint8_t out[32])
|
||||
{
|
||||
DIGEST_CTX ctx = *dgst_ctx;
|
||||
uint8_t dgst[64];
|
||||
size_t dgstlen;
|
||||
|
||||
if (digest_finish(&ctx, dgst, &dgstlen) != 1
|
||||
|| tls13_hkdf_expand_label(dgst_ctx->digest, secret, label, dgst, 32, dgstlen, out) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
data to be signed in certificate_verify:
|
||||
- A string that consists of octet 32 (0x20) repeated 64 times
|
||||
- The context string
|
||||
- A single 0 byte which serves as the separator
|
||||
- The content to be signed
|
||||
*/
|
||||
int tls13_sign(const SM2_KEY *key, const DIGEST_CTX *dgst_ctx, uint8_t *sig, size_t *siglen, int is_server)
|
||||
{
|
||||
uint8_t client_context_str[] = "TLS 1.3, client CertificateVerify";
|
||||
uint8_t server_context_str[] = "TLS 1.3, server CertificateVerify";
|
||||
|
||||
SM2_SIGN_CTX sm2_ctx;
|
||||
DIGEST_CTX temp_dgst_ctx;
|
||||
uint8_t prefix[64];
|
||||
uint8_t *context_str = is_server ? server_context_str : client_context_str;
|
||||
size_t context_str_len = sizeof(client_context_str);
|
||||
uint8_t dgst[64];
|
||||
size_t dgstlen;
|
||||
|
||||
memset(prefix, 0x20, 64);
|
||||
temp_dgst_ctx = *dgst_ctx;
|
||||
digest_finish(&temp_dgst_ctx, dgst, &dgstlen);
|
||||
|
||||
sm2_sign_init(&sm2_ctx, key, SM2_DEFAULT_ID);
|
||||
sm2_sign_update(&sm2_ctx, prefix, 64);
|
||||
sm2_sign_update(&sm2_ctx, context_str, context_str_len);
|
||||
sm2_sign_update(&sm2_ctx, dgst, dgstlen);
|
||||
sm2_sign_finish(&sm2_ctx, sig, siglen);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tls13_verify(const SM2_KEY *key, const DIGEST_CTX *dgst_ctx, const uint8_t *sig, size_t siglen, int is_server)
|
||||
{
|
||||
uint8_t client_context_str[] = "TLS 1.3, client CertificateVerify";
|
||||
uint8_t server_context_str[] = "TLS 1.3, server CertificateVerify";
|
||||
|
||||
int ret;
|
||||
SM2_SIGN_CTX sm2_ctx;
|
||||
DIGEST_CTX temp_dgst_ctx;
|
||||
uint8_t prefix[64];
|
||||
uint8_t dgst[64];
|
||||
size_t dgstlen;
|
||||
|
||||
memset(prefix, 0x20, 64);
|
||||
temp_dgst_ctx = *dgst_ctx;
|
||||
digest_finish(&temp_dgst_ctx, dgst, &dgstlen);
|
||||
|
||||
sm2_verify_init(&sm2_ctx, key, SM2_DEFAULT_ID);
|
||||
sm2_verify_update(&sm2_ctx, prefix, 64);
|
||||
sm2_verify_update(&sm2_ctx, is_server ? server_context_str : client_context_str, sizeof(server_context_str));
|
||||
sm2_verify_update(&sm2_ctx, dgst, dgstlen);
|
||||
ret = sm2_verify_finish(&sm2_ctx, sig, siglen);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
verify_data in Finished
|
||||
|
||||
finished_key =
|
||||
HKDF-Expand-Label(BaseKey, "finished", "", Hash.length)
|
||||
Structure of this message:
|
||||
struct {
|
||||
opaque verify_data[Hash.length];
|
||||
} Finished;
|
||||
The verify_data value is computed as follows:
|
||||
verify_data =
|
||||
HMAC(finished_key,
|
||||
Transcript-Hash(Handshake Context,
|
||||
Certificate*, CertificateVerify*))
|
||||
*/
|
||||
|
||||
int tls13_compute_verify_data(const uint8_t *handshake_traffic_secret,
|
||||
const DIGEST_CTX *dgst_ctx, uint8_t *verify_data, size_t *verify_data_len)
|
||||
{
|
||||
DIGEST_CTX temp_dgst_ctx;
|
||||
uint8_t dgst[64];
|
||||
size_t dgstlen;
|
||||
uint8_t finished_key[64];
|
||||
size_t finished_key_len;
|
||||
|
||||
temp_dgst_ctx = *dgst_ctx;
|
||||
digest_finish(&temp_dgst_ctx, dgst, &dgstlen);
|
||||
finished_key_len = dgstlen;
|
||||
|
||||
tls13_hkdf_expand_label(dgst_ctx->digest, handshake_traffic_secret,
|
||||
"finished", NULL, 0, finished_key_len, finished_key);
|
||||
|
||||
hmac(dgst_ctx->digest, finished_key, finished_key_len, dgst, dgstlen, verify_data, verify_data_len);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
Handshakes
|
||||
|
||||
*/
|
||||
|
||||
int tls_ext_supported_versions_to_bytes(const int *versions, size_t versions_count,
|
||||
uint8_t **out, size_t *outlen)
|
||||
{
|
||||
@@ -597,56 +891,6 @@ int tls13_record_get_handshake_encrypted_extensions(const uint8_t *record)
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tls13_sign(const SM2_KEY *key, const DIGEST_CTX *dgst_ctx, uint8_t *sig, size_t *siglen, int is_server)
|
||||
{
|
||||
uint8_t client_context_str[] = "TLS 1.3, client CertificateVerify";
|
||||
uint8_t server_context_str[] = "TLS 1.3, server CertificateVerify";
|
||||
|
||||
SM2_SIGN_CTX sm2_ctx;
|
||||
DIGEST_CTX temp_dgst_ctx;
|
||||
uint8_t prefix[64];
|
||||
uint8_t *context_str = is_server ? server_context_str : client_context_str;
|
||||
size_t context_str_len = sizeof(client_context_str);
|
||||
uint8_t dgst[64];
|
||||
size_t dgstlen;
|
||||
|
||||
memset(prefix, 0x20, 64);
|
||||
temp_dgst_ctx = *dgst_ctx;
|
||||
digest_finish(&temp_dgst_ctx, dgst, &dgstlen);
|
||||
|
||||
sm2_sign_init(&sm2_ctx, key, SM2_DEFAULT_ID);
|
||||
sm2_sign_update(&sm2_ctx, prefix, 64);
|
||||
sm2_sign_update(&sm2_ctx, context_str, context_str_len);
|
||||
sm2_sign_update(&sm2_ctx, dgst, dgstlen);
|
||||
sm2_sign_finish(&sm2_ctx, sig, siglen);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tls13_verify(const SM2_KEY *key, const DIGEST_CTX *dgst_ctx, const uint8_t *sig, size_t siglen, int is_server)
|
||||
{
|
||||
uint8_t client_context_str[] = "TLS 1.3, client CertificateVerify";
|
||||
uint8_t server_context_str[] = "TLS 1.3, server CertificateVerify";
|
||||
|
||||
int ret;
|
||||
SM2_SIGN_CTX sm2_ctx;
|
||||
DIGEST_CTX temp_dgst_ctx;
|
||||
uint8_t prefix[64];
|
||||
uint8_t dgst[64];
|
||||
size_t dgstlen;
|
||||
|
||||
memset(prefix, 0x20, 64);
|
||||
temp_dgst_ctx = *dgst_ctx;
|
||||
digest_finish(&temp_dgst_ctx, dgst, &dgstlen);
|
||||
|
||||
sm2_verify_init(&sm2_ctx, key, SM2_DEFAULT_ID);
|
||||
sm2_verify_update(&sm2_ctx, prefix, 64);
|
||||
sm2_verify_update(&sm2_ctx, is_server ? server_context_str : client_context_str, sizeof(server_context_str));
|
||||
sm2_verify_update(&sm2_ctx, dgst, dgstlen);
|
||||
ret = sm2_verify_finish(&sm2_ctx, sig, siglen);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
ClientHello.Extensions.signature_algorithms 列出客户端支持的签名+哈希算法
|
||||
@@ -814,26 +1058,6 @@ int tls13_record_get_handshake_certificate(const uint8_t *record, uint8_t *data,
|
||||
}
|
||||
|
||||
|
||||
int tls13_compute_verify_data(const uint8_t *handshake_traffic_secret,
|
||||
const DIGEST_CTX *dgst_ctx, uint8_t *verify_data, size_t *verify_data_len)
|
||||
{
|
||||
DIGEST_CTX temp_dgst_ctx;
|
||||
uint8_t dgst[64];
|
||||
size_t dgstlen;
|
||||
uint8_t finished_key[64];
|
||||
size_t finished_key_len;
|
||||
|
||||
temp_dgst_ctx = *dgst_ctx;
|
||||
digest_finish(&temp_dgst_ctx, dgst, &dgstlen);
|
||||
finished_key_len = dgstlen;
|
||||
|
||||
tls13_hkdf_expand_label(dgst_ctx->digest, handshake_traffic_secret,
|
||||
"finished", NULL, 0, finished_key_len, finished_key);
|
||||
|
||||
hmac(dgst_ctx->digest, finished_key, finished_key_len, dgst, dgstlen, verify_data, verify_data_len);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1839,95 +2063,3 @@ int tls13_accept(TLS_CONNECT *conn, int port,
|
||||
tls_trace("Connection Established!\n\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int tls13_send(TLS_CONNECT *conn, const uint8_t *data, size_t datalen, size_t padding_len)
|
||||
{
|
||||
const BLOCK_CIPHER_KEY *key;
|
||||
const uint8_t *iv;
|
||||
uint8_t *seq_num;
|
||||
uint8_t *record = conn->record;
|
||||
size_t recordlen;
|
||||
|
||||
tls_trace("<<<< [ApplicationData]\n");
|
||||
|
||||
if (conn->is_client) {
|
||||
key = &conn->client_write_key;
|
||||
iv = conn->client_write_iv;
|
||||
seq_num = conn->client_seq_num;
|
||||
} else {
|
||||
key = &conn->server_write_key;
|
||||
iv = conn->server_write_iv;
|
||||
seq_num = conn->server_seq_num;
|
||||
}
|
||||
|
||||
if (tls13_gcm_encrypt(key, iv, padding_len,
|
||||
seq_num, TLS_record_application_data, data, datalen,
|
||||
record + 5, &recordlen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
record[0] = TLS_record_application_data;
|
||||
record[1] = TLS_version_tls12 >> 8;
|
||||
record[2] = TLS_version_tls12 & 0xff;
|
||||
record[3] = recordlen >> 8;
|
||||
record[4] = recordlen;
|
||||
recordlen += 5;
|
||||
|
||||
tls_record_send(record, recordlen, conn->sock);
|
||||
tls_seq_num_incr(seq_num);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tls13_recv(TLS_CONNECT *conn, uint8_t *data, size_t *datalen)
|
||||
{
|
||||
int record_type;
|
||||
uint8_t *record = conn->record;
|
||||
size_t recordlen;
|
||||
const BLOCK_CIPHER_KEY *key;
|
||||
const uint8_t *iv;
|
||||
uint8_t *seq_num;
|
||||
|
||||
|
||||
tls_trace(">>>> [ApplicationData]\n");
|
||||
|
||||
if (conn->is_client) {
|
||||
key = &conn->client_write_key;
|
||||
iv = conn->client_write_iv;
|
||||
seq_num = conn->client_seq_num;
|
||||
} else {
|
||||
key = &conn->server_write_key;
|
||||
iv = conn->server_write_iv;
|
||||
seq_num = conn->server_seq_num;
|
||||
}
|
||||
|
||||
if (tls12_record_recv(record, &recordlen, conn->sock) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (record[0] != TLS_record_application_data) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (tls13_gcm_decrypt(key, iv,
|
||||
seq_num, record + 5, recordlen - 5,
|
||||
&record_type, data, datalen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
tls_seq_num_incr(seq_num);
|
||||
|
||||
|
||||
if (record_type != TLS_record_application_data) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
347
src/tls_cipher.c
347
src/tls_cipher.c
@@ -1,347 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2021 - 2021 The GmSSL Project. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. All advertising materials mentioning features or use of this
|
||||
* software must display the following acknowledgment:
|
||||
* "This product includes software developed by the GmSSL Project.
|
||||
* (http://gmssl.org/)"
|
||||
*
|
||||
* 4. The name "GmSSL Project" must not be used to endorse or promote
|
||||
* products derived from this software without prior written
|
||||
* permission. For written permission, please contact
|
||||
* guanzhi1980@gmail.com.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "GmSSL"
|
||||
* nor may "GmSSL" appear in their names without prior written
|
||||
* permission of the GmSSL Project.
|
||||
*
|
||||
* 6. Redistributions of any form whatsoever must retain the following
|
||||
* acknowledgment:
|
||||
* "This product includes software developed by the GmSSL Project
|
||||
* (http://gmssl.org/)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE GmSSL PROJECT ``AS IS'' AND ANY
|
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE GmSSL PROJECT OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <time.h>
|
||||
#include <gmssl/tls.h>
|
||||
#include <gmssl/x509.h>
|
||||
#include <gmssl/rand.h>
|
||||
#include <gmssl/error.h>
|
||||
#include <gmssl/digest.h>
|
||||
#include <gmssl/hkdf.h>
|
||||
#include "mem.h"
|
||||
|
||||
|
||||
|
||||
int tls_prf(const uint8_t *secret, size_t secretlen, const char *label,
|
||||
const uint8_t *seed, size_t seedlen,
|
||||
const uint8_t *more, size_t morelen,
|
||||
size_t outlen, uint8_t *out)
|
||||
{
|
||||
SM3_HMAC_CTX inited_hmac_ctx;
|
||||
SM3_HMAC_CTX hmac_ctx;
|
||||
uint8_t A[32];
|
||||
uint8_t hmac[32];
|
||||
size_t len;
|
||||
|
||||
if (!secret || !secretlen || !label || !seed || !seedlen
|
||||
|| (!more && morelen) || !outlen || !out) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
sm3_hmac_init(&inited_hmac_ctx, secret, secretlen);
|
||||
|
||||
memcpy(&hmac_ctx, &inited_hmac_ctx, sizeof(SM3_HMAC_CTX));
|
||||
sm3_hmac_update(&hmac_ctx, (uint8_t *)label, strlen(label));
|
||||
sm3_hmac_update(&hmac_ctx, seed, seedlen);
|
||||
sm3_hmac_update(&hmac_ctx, more, morelen);
|
||||
sm3_hmac_finish(&hmac_ctx, A);
|
||||
|
||||
memcpy(&hmac_ctx, &inited_hmac_ctx, sizeof(SM3_HMAC_CTX));
|
||||
sm3_hmac_update(&hmac_ctx, A, sizeof(A));
|
||||
sm3_hmac_update(&hmac_ctx, (uint8_t *)label, strlen(label));
|
||||
sm3_hmac_update(&hmac_ctx, seed, seedlen);
|
||||
sm3_hmac_update(&hmac_ctx, more, morelen);
|
||||
sm3_hmac_finish(&hmac_ctx, hmac);
|
||||
|
||||
len = outlen < sizeof(hmac) ? outlen : sizeof(hmac);
|
||||
memcpy(out, hmac, len);
|
||||
out += len;
|
||||
outlen -= len;
|
||||
|
||||
while (outlen) {
|
||||
memcpy(&hmac_ctx, &inited_hmac_ctx, sizeof(SM3_HMAC_CTX));
|
||||
sm3_hmac_update(&hmac_ctx, A, sizeof(A));
|
||||
sm3_hmac_finish(&hmac_ctx, A);
|
||||
|
||||
memcpy(&hmac_ctx, &inited_hmac_ctx, sizeof(SM3_HMAC_CTX));
|
||||
sm3_hmac_update(&hmac_ctx, A, sizeof(A));
|
||||
sm3_hmac_update(&hmac_ctx, (uint8_t *)label, strlen(label));
|
||||
sm3_hmac_update(&hmac_ctx, seed, seedlen);
|
||||
sm3_hmac_update(&hmac_ctx, more, morelen);
|
||||
sm3_hmac_finish(&hmac_ctx, hmac);
|
||||
|
||||
len = outlen < sizeof(hmac) ? outlen : sizeof(hmac);
|
||||
memcpy(out, hmac, len);
|
||||
out += len;
|
||||
outlen -= len;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
HKDF-Expand-Label(Secret, Label, Context, Length) =
|
||||
HKDF-Expand(Secret, HkdfLabel, Length);
|
||||
|
||||
HkdfLabel = struct {
|
||||
uint16 length = Length;
|
||||
opaque label<7..255> = "tls13 " + Label;
|
||||
opaque context<0..255> = Context; }
|
||||
|
||||
Derive-Secret(Secret, Label, Messages) =
|
||||
HKDF-Expand-Label(Secret, Label, Hash(Messages), Hash.length)
|
||||
|
||||
*/
|
||||
|
||||
int tls13_hkdf_extract(const DIGEST *digest, const uint8_t salt[32], const uint8_t in[32], uint8_t out[32])
|
||||
{
|
||||
size_t dgstlen;
|
||||
if (hkdf_extract(digest, salt, 32, in, 32, out, &dgstlen) != 1
|
||||
|| dgstlen != 32) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tls13_hkdf_expand_label(const DIGEST *digest, const uint8_t secret[32],
|
||||
const char *label, const uint8_t *context, size_t context_len,
|
||||
size_t outlen, uint8_t *out)
|
||||
{
|
||||
uint8_t label_len;
|
||||
uint8_t hkdf_label[2 + 256 + 256];
|
||||
uint8_t *p = hkdf_label;
|
||||
size_t hkdf_label_len = 0;
|
||||
|
||||
label_len = strlen("tls13") + strlen(label);
|
||||
tls_uint16_to_bytes((uint16_t)outlen, &p, &hkdf_label_len);
|
||||
tls_uint8_to_bytes(label_len, &p, &hkdf_label_len);
|
||||
tls_array_to_bytes((uint8_t *)"tls13", strlen("tls13"), &p, &hkdf_label_len);
|
||||
tls_array_to_bytes((uint8_t *)label, strlen(label), &p, &hkdf_label_len);
|
||||
tls_uint8array_to_bytes(context, context_len, &p, &hkdf_label_len);
|
||||
|
||||
hkdf_expand(digest, secret, 32, hkdf_label, hkdf_label_len, outlen, out);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tls13_derive_secret(const uint8_t secret[32], const char *label, const DIGEST_CTX *dgst_ctx, uint8_t out[32])
|
||||
{
|
||||
DIGEST_CTX ctx = *dgst_ctx;
|
||||
uint8_t dgst[64];
|
||||
size_t dgstlen;
|
||||
|
||||
if (digest_finish(&ctx, dgst, &dgstlen) != 1
|
||||
|| tls13_hkdf_expand_label(dgst_ctx->digest, secret, label, dgst, 32, dgstlen, out) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tls_cbc_encrypt(const SM3_HMAC_CTX *inited_hmac_ctx, const SM4_KEY *enc_key,
|
||||
const uint8_t seq_num[8], const uint8_t header[5],
|
||||
const uint8_t *in, size_t inlen, uint8_t *out, size_t *outlen)
|
||||
{
|
||||
SM3_HMAC_CTX hmac_ctx;
|
||||
uint8_t last_blocks[32 + 16] = {0};
|
||||
uint8_t *mac, *padding, *iv;
|
||||
int rem, padding_len;
|
||||
int i;
|
||||
|
||||
if (!inited_hmac_ctx || !enc_key || !seq_num || !header || (!in && inlen) || !out || !outlen) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (inlen > (1 << 14)) {
|
||||
error_print("invalid tls record data length %zu\n", inlen);
|
||||
return -1;
|
||||
}
|
||||
|
||||
rem = (inlen + 32) % 16;
|
||||
memcpy(last_blocks, in + inlen - rem, rem);
|
||||
mac = last_blocks + rem;
|
||||
|
||||
memcpy(&hmac_ctx, inited_hmac_ctx, sizeof(SM3_HMAC_CTX));
|
||||
sm3_hmac_update(&hmac_ctx, seq_num, 8);
|
||||
sm3_hmac_update(&hmac_ctx, header, 5);
|
||||
sm3_hmac_update(&hmac_ctx, in, inlen);
|
||||
sm3_hmac_finish(&hmac_ctx, mac);
|
||||
|
||||
padding = mac + 32;
|
||||
padding_len = 16 - rem - 1;
|
||||
for (i = 0; i <= padding_len; i++) {
|
||||
padding[i] = padding_len;
|
||||
}
|
||||
|
||||
iv = out;
|
||||
if (rand_bytes(iv, 16) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
out += 16;
|
||||
|
||||
if (inlen >= 16) {
|
||||
sm4_cbc_encrypt(enc_key, iv, in, inlen/16, out);
|
||||
out += inlen - rem;
|
||||
iv = out - 16;
|
||||
}
|
||||
sm4_cbc_encrypt(enc_key, iv, last_blocks, sizeof(last_blocks)/16, out);
|
||||
*outlen = 16 + inlen - rem + sizeof(last_blocks);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tls_cbc_decrypt(const SM3_HMAC_CTX *inited_hmac_ctx, const SM4_KEY *dec_key,
|
||||
const uint8_t seq_num[8], const uint8_t enced_header[5],
|
||||
const uint8_t *in, size_t inlen, uint8_t *out, size_t *outlen)
|
||||
{
|
||||
SM3_HMAC_CTX hmac_ctx;
|
||||
const uint8_t *iv;
|
||||
const uint8_t *padding;
|
||||
const uint8_t *mac;
|
||||
uint8_t header[5];
|
||||
int padding_len;
|
||||
int i;
|
||||
|
||||
if (!inited_hmac_ctx || !dec_key || !seq_num || !enced_header || !in || !inlen || !out || !outlen) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (inlen % 16
|
||||
|| inlen < (16 + 0 + 32 + 16) // iv + data + mac + padding
|
||||
|| inlen > (16 + (1<<14) + 32 + 256)) {
|
||||
error_print("invalid tls cbc ciphertext length %zu\n", inlen);
|
||||
return -1;
|
||||
}
|
||||
|
||||
iv = in;
|
||||
in += 16;
|
||||
inlen -= 16;
|
||||
|
||||
sm4_cbc_decrypt(dec_key, iv, in, inlen/16, out);
|
||||
|
||||
padding_len = out[inlen - 1];
|
||||
padding = out + inlen - padding_len - 1;
|
||||
if (padding < out + 32) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
for (i = 0; i < padding_len; i++) {
|
||||
if (padding[i] != padding_len) {
|
||||
error_print("tls ciphertext cbc-padding check failure");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
*outlen = inlen - 32 - padding_len - 1;
|
||||
header[0] = enced_header[0];
|
||||
header[1] = enced_header[1];
|
||||
header[2] = enced_header[2];
|
||||
header[3] = (*outlen) >> 8;
|
||||
header[4] = (*outlen);
|
||||
mac = padding - 32;
|
||||
|
||||
memcpy(&hmac_ctx, inited_hmac_ctx, sizeof(SM3_HMAC_CTX));
|
||||
sm3_hmac_update(&hmac_ctx, seq_num, 8);
|
||||
sm3_hmac_update(&hmac_ctx, header, 5);
|
||||
sm3_hmac_update(&hmac_ctx, out, *outlen);
|
||||
if (sm3_hmac_finish_and_verify(&hmac_ctx, mac) != 1) {
|
||||
error_print("tls ciphertext mac check failure");
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tls_sign_server_ecdh_params(const SM2_KEY *server_sign_key,
|
||||
const uint8_t client_random[32], const uint8_t server_random[32],
|
||||
int curve, const SM2_POINT *point, uint8_t *sig, size_t *siglen)
|
||||
{
|
||||
uint8_t server_ecdh_params[69];
|
||||
SM2_SIGN_CTX sign_ctx;
|
||||
|
||||
if (!server_sign_key || !client_random || !server_random
|
||||
|| curve != TLS_curve_sm2p256v1 || !point || !sig || !siglen) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
server_ecdh_params[0] = TLS_curve_type_named_curve;
|
||||
server_ecdh_params[1] = curve >> 8;
|
||||
server_ecdh_params[2] = curve;
|
||||
server_ecdh_params[3] = 65;
|
||||
sm2_point_to_uncompressed_octets(point, server_ecdh_params + 4);
|
||||
|
||||
sm2_sign_init(&sign_ctx, server_sign_key, SM2_DEFAULT_ID);
|
||||
sm2_sign_update(&sign_ctx, client_random, 32);
|
||||
sm2_sign_update(&sign_ctx, server_random, 32);
|
||||
sm2_sign_update(&sign_ctx, server_ecdh_params, 69);
|
||||
sm2_sign_finish(&sign_ctx, sig, siglen);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int tls_verify_server_ecdh_params(const SM2_KEY *server_sign_key,
|
||||
const uint8_t client_random[32], const uint8_t server_random[32],
|
||||
int curve, const SM2_POINT *point, const uint8_t *sig, size_t siglen)
|
||||
{
|
||||
int ret;
|
||||
uint8_t server_ecdh_params[69];
|
||||
SM2_SIGN_CTX verify_ctx;
|
||||
|
||||
if (!server_sign_key || !client_random || !server_random
|
||||
|| curve != TLS_curve_sm2p256v1 || !point || !sig || !siglen
|
||||
|| siglen > TLS_MAX_SIGNATURE_SIZE) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
server_ecdh_params[0] = TLS_curve_type_named_curve;
|
||||
server_ecdh_params[1] = curve >> 8;
|
||||
server_ecdh_params[2] = curve;
|
||||
server_ecdh_params[3] = 65;
|
||||
sm2_point_to_uncompressed_octets(point, server_ecdh_params + 4);
|
||||
|
||||
sm2_verify_init(&verify_ctx, server_sign_key, SM2_DEFAULT_ID);
|
||||
sm2_verify_update(&verify_ctx, client_random, 32);
|
||||
sm2_verify_update(&verify_ctx, server_random, 32);
|
||||
sm2_verify_update(&verify_ctx, server_ecdh_params, 69);
|
||||
ret = sm2_verify_finish(&verify_ctx, sig, siglen);
|
||||
if (ret != 1) error_print();
|
||||
return ret;
|
||||
}
|
||||
Reference in New Issue
Block a user