TLSv1.2 AES128-GCM-SHA256 TestVector 및 분석과정 정리
- 작성자
- 고친과정
- 2000년 ~ 2015년 : 암/복호화 API 개인적으로 구현. (이 구현사항들을 개조하여 본 문서를 도출 할 수 있는 근거 마련)
- 2018년 10월 15일 : 처음씀
- 2018년 11월 23일 : 검증 데이터 산출 관련 OpenSSL v1.0.2p 와 v1.1.1 을 사용한 포팅과 함께 추가 검증으로 Test Vector 다량 확보 및 확증
- 2018년 12월 19일 : 본 문서 공개
Contents
- 1. TLSv1.2 AES128-GCM-SHA256 TestVector 및 분석과정 정리
- 1.1. 개요
- 1.2. 기초 구현 예제
- 1.2.1. PRF(Pseudo Random Function) in RFC5246 : The Transport Layer Security (TLS) Protocol Version 1.2
- 1.2.2. Big interger increment 간략 예제
- 1.2.3. XOR block 간략 예제
- 1.2.4. Right shift block 간략 예제
- 1.2.5. Multiplication in GF(2^128) 개요
- 1.2.6. GHASH 간략 예제
- 1.2.7. AES-GCM-GHASH 간략 예제
- 1.2.8. AES-GCM-GCTR 간략 예제
- 1.2.9. AES-GCM Encrypt/Decrypt 간략 예제
- 1.2.10. TLS v1.2 record AES128-GCM-SHA256 Encrypt/Decrypt 간략 예제
- 1.3. 기초 Test Vector
- 1.4. TLS v1.2 record 분석 및 검증
- 1.5. Test Vector 분석 및 검증 결과 (최종 정리)
- 1.6. 참고자료
1.1. 개요
본 정리내용은 TLS(SSL) v1.2 표준에서의 AEAD algorithm를 이해하기 위해서 필요한 Parameter(용어) 및 암호화/복호화 과정들을 분석하고 이에 대한 핵심 요점만 정리하는 것을 목표로 합니다.
AEAD 관점. 특히 AES128-GCM-SHA256을 기준으로 분석 과정을 전개하면서 아름다운 코드는 아니지만 별도의 간략한 약식 형태의 검증코드를 만들면서 정리하였습니다.
여기서 AES-GCM(AES Galois Counter Mode) 을 어떻게 구현하는가? 그리고 TLS에서는 이를 어떻게 활용하는가를 이해할 수 있는 기초 자료가 되었으면 합니다.
더 나아가서 Intel CPU에서 지원하는 AES-NI 가속부와 병렬 처리 방안을 도출할 수 있으면 좋겠습니다.
혹시 이와 관련하여 성능향상에 대한 저와 같은 고민 하시는 분이 계시다면 함께 논의하는 자리가 있으면 더욱 좋겠습니다.
AEAD 관점. 특히 AES128-GCM-SHA256을 기준으로 분석 과정을 전개하면서 아름다운 코드는 아니지만 별도의 간략한 약식 형태의 검증코드를 만들면서 정리하였습니다.
여기서 AES-GCM(AES Galois Counter Mode) 을 어떻게 구현하는가? 그리고 TLS에서는 이를 어떻게 활용하는가를 이해할 수 있는 기초 자료가 되었으면 합니다.
더 나아가서 Intel CPU에서 지원하는 AES-NI 가속부와 병렬 처리 방안을 도출할 수 있으면 좋겠습니다.
혹시 이와 관련하여 성능향상에 대한 저와 같은 고민 하시는 분이 계시다면 함께 논의하는 자리가 있으면 더욱 좋겠습니다.
- Master-Secret
- Pre-Master-Secret 으로부터 label을 "master secret"으로 하여 HMAC-SHA256으로 산출
- 즉, <Master-Secret> = HMAC-SHA256(<Pre-Master-Secret>, "master secret", <ClientRandom + ServerRandom>, 48-Bytes-Output)
- KeyBlock
- Master-Secret으로부터 label을 "key expansion"으로 하여 HMAC-SHA256으로 산출
- 즉, <KeyBlock> = HMAC-SHA256(<Master-Secret>, "key expansion", <SeverRandom + ClientRandom>, 48-Bytes-Output)
- TLSv1.2 header
- 0x17 (TLS record type: application-data)
- 0x03 0x03 (TLS record version)
- 0xNN 0xMM (TLS record length: IV + PlainText-Or-CipherText + Tag-Or-MAC)
- AAD(Additional-Authenticated-Data)
- 0xAA 0xBB 0xCC 0xDD 0xEE 0xFF 0xGG 0xHH (Record sequence number, 처음은 1부터 시작하여 BigNumber 증가)
- 0x17 (TLS record type: application-data)
- 0x03 0x03 (TLS record version)
- 0xNN 0xMM (TLS record length: PlainText)
- Key (KeyBlock으로부터 산출)
- 16-Bytes AES128 Key
- Salt (KeyBlock으로부터 산출)
- 4-Bytes
- IV (KeyBlock으로부터 산출하거나 임의의 값을 사용하거나 무관)
- 8-Bytes
- MAC/HMAC/Tag/HASH (값의 위변조 유무를 식별)
- Unused (AEAD Cipher는 MAC 대신 Tag를 사용. 즉, Cipher-suite의 SHA256은 KeyBlock 산출용으로만 활용됨.)
- 실제 TLS record layout
- <TLSv1.2 header><IV><CipherText><Tag>
- CipherText 및 Tag를 AEAD Cipher로 Encrypt/Decrypt 할 때
- <AAD>, <Salt><IV>, <PlainText-Or-CipherText>, <Tag>
- 기타 잘못 이해할 수 있는 사항들 정리
- SHA256, P-SHA256, HMAC-SHA256 은 같은게 아니고 우측항목이 좌측항목에 의해서 응용된 기능성의 확장 개념임
- HMAC은 Secret + Label + Seed 의 조합력을 갖추고 재귀적인 파생형태의 Hash를 도출
- AAD는 암호화에 관여하지 않지만 인증값(Tag or MAC)의 변화성에 기여함
- IV는 크게 고정된 비밀값(Salt)형태와 노출되는 공개값(IV)이 각 사용처에 따라서 정의되고 운용될 수 있음
- SHA256, P-SHA256, HMAC-SHA256 은 같은게 아니고 우측항목이 좌측항목에 의해서 응용된 기능성의 확장 개념임
1.2. 기초 구현 예제
1.2.1. PRF(Pseudo Random Function) in RFC5246 : The Transport Layer Security (TLS) Protocol Version 1.2
TLS 프로토콜(Protocol)에서 비밀키 도출을 위한 KeyBlock 산출에 핵심적인 알고리즘
- PRF(secret, label, seed) = P_<hash>(secret, label + seed)
- P_hash(secret, seed) = HMAC_hash(secret, A(1) + seed) + HMAC_hash(secret, A(2) + seed) + HMAC_hash(secret, A(3) + seed) + ...
- A(0) = seed
- A(i) = HMAC_hash(secret, A(i-1))
- P_hash(secret, seed) = HMAC_hash(secret, A(1) + seed) + HMAC_hash(secret, A(2) + seed) + HMAC_hash(secret, A(3) + seed) + ...
Master-Secret[0..47]: pre-master-secret, label="master secret", client-random + server-random
- Key-Block : master-secret, label="key expansion", server-random + client-random
- client write MAC key
- server write MAC key
- client write encryption key
- server write encryption key
- client write IV
- server write IV
- Key-Block : master-secret, label="key expansion", server-random + client-random
1.2.2. Big interger increment 간략 예제
큰 정수를 +1 하는 성능은 무시한 구현
"*((typeof bigint *)(&bigint)) += 1"
void bigint_increment( void *s_bigint_ptr /* 정수 저장 포인터 */, size_t s_size /* 정수의 크기 */) { uint8_t *s_uint8_ptr = (uint8_t *)s_bigint_ptr; do { ++s_uint8_ptr[--s_size]; }while((s_size > ((size_t)0u)) && (s_uint8_ptr[s_size] == ((uint8_t)0u)) /* is overflow */); }
1.2.3. XOR block 간략 예제
큰 비트열을 XOR하는 성능은 무시한 구현
"to ^= from"
void xor_block( void *s_to_ptr /* XOR 피연산자 */, const void *s_from_ptr /* XOR 입력 값 */, size_t s_size /* 크기 */) { uint8_t *s_to = (uint8_t *)s_to_ptr; const uint8_t *s_from = (const uint8_t *)s_from_ptr; do { --s_size; s_to[s_size] ^= s_from[s_size]; }while(s_size > ((size_t)0u)); }
1.2.4. Right shift block 간략 예제
큰 비트열을 오른쪽으로 쉬프트 하는 성능은 무시한 구현
"*((typeof block *)(&block)) >>= 1"
void rightshift_block(void *s_block_ptr, size_t s_size) { uint8_t *s_uint8_ptr; for(s_uint8_ptr = (uint8_t *)s_block_ptr;;) { --s_size; s_uint8_ptr[s_size] = (s_uint8_ptr[s_size] >> 1); if(s_size <= ((size_t)0u)) { break; } if(s_uint8_ptr[s_size - ((size_t)1u)] & ((uint8_t)0x01u)) { s_uint8_ptr[s_size] |= (uint8_t)0x80u; } } }
1.2.5. Multiplication in GF(2^128) 개요
"Multiplication in GF"를 산출하는 성능은 무시한 구현. (GHASH를 구현하기 위한 기초 함수)
Algorithm 1 Multiplication in Computes the value of
Algorithm 1 Multiplication in Computes the value of
Z = X · Y , where X, Y and Z ∈ GF(2128)
.
concat is '||' R = 11100001b || 0^120 Z ← 0, V ← X for i =0 to 127 do if Yi =1 then Z ← Z xor V end if if V127 =0 then V ← rightshift(V) else V ← rightshift(V) xor R end if end for return Z
1.2.6. GHASH 간략 예제
HASH 알고리즘의 일종으로 AEAD 운영모드의 핵심적인 역할
#define def_hwport_ghash_block_size (128 / 8) void ghash_start(uint8_t *y) { (void)memset(y, 0, (size_t)def_hwport_ghash_block_size); /* Y_0 = 0^128 */ } void ghash(const uint8_t *h, const uint8_t *x, size_t xlen, uint8_t *y) { size_t m = xlen / def_hwport_ghash_block_size, i; const uint8_t *xpos = x; uint8_t tmp[def_hwport_ghash_block_size]; for (i = 0; i < m; i++) { /* Y_i = (Y^(i-1) XOR X_i) dot H */ xor_block( (void *)y, (const void *)xpos, (size_t)def_hwport_ghash_block_size ); xpos += def_hwport_ghash_block_size; gf_mult128(y, h, tmp); memcpy(y, tmp, sizeof(tmp)); } if (x + xlen > xpos) { size_t last = ((size_t)x) + xlen - ((size_t)xpos); memcpy(tmp, xpos, last); memset(tmp + last, 0, sizeof(tmp) - last); /* Y_i = (Y^(i-1) XOR X_i) dot H */ xor_block( (void *)y, (const void *)tmp, (size_t)def_hwport_ghash_block_size ); gf_mult128(y, h, tmp); memcpy(y, tmp, sizeof(tmp)); } /* Return Y_m */ }
1.2.7. AES-GCM-GHASH 간략 예제
- u = 128 * ceillen(C)/128 - len(C)
- v = 128 * ceillen(A)/128 - len(A)
- S = GHASH_H(A || 0^v || C || 0^u || len(A)64 || len(C)64)
- (i.e., zero padded to block size A || C and lengths of each in bits)
- (i.e., zero padded to block size A || C and lengths of each in bits)
void aes_gcm_ghash( const uint8_t *H, const uint8_t *aad, size_t aad_len, const uint8_t *crypt, size_t crypt_len, uint8_t *S) { uint8_t len_buf[16]; ghash_start(S); ghash(H, aad, aad_len, S); ghash(H, crypt, crypt_len, S); PUT_BE64(len_buf, aad_len * 8); PUT_BE64(len_buf + 8, crypt_len * 8); ghash(H, len_buf, sizeof(len_buf), S); }
1.2.8. AES-GCM-GCTR 간략 예제
#define def_hwport_aes_block_size (128 / 8) /* AES 알고리즘의 block size는 모두 16 bytes */ static void aes_gctr( void *rk /* round-key */, const uint8_t *icb /* initial-count-block */, const uint8_t *x, size_t xlen, uint8_t *y) { size_t i, n, last; uint8_t cb[def_hwport_aes_block_size], tmp[def_hwport_aes_block_size]; const uint8_t *xpos = x; uint8_t *ypos = y; if (xlen == 0) return; n = xlen / 16; memcpy(cb, icb, def_hwport_aes_block_size); for (i = 0; i < n; i++) { /* Full blocks */ xor_block( encrypt_aes_ecb( memcpy(ypos, cb, def_hwport_aes_block_size), def_hwport_aes_block_size, rk ), (const void *)xpos, (size_t)def_hwport_aes_block_size ); xpos += def_hwport_aes_block_size; ypos += def_hwport_aes_block_size; bigint_increment( (void *)(&cb[def_hwport_aes_block_size - sizeof(uint32_t)]), (size_t)sizeof(uint32_t) ); } last = ((size_t)x) + xlen - ((size_t)xpos); if (last) { /* Last, partial block */ encrypt_aes_ecb( memcpy(tmp, cb, def_hwport_aes_block_size), def_hwport_aes_block_size, rk ); for (i = 0; i < last; i++) *ypos++ = *xpos++ ^ tmp[i]; } } void aes_gcm_gctr( void *rk /* round-key */, const uint8_t *J0, const uint8_t *in, size_t len, uint8_t *out) { uint8_t J0inc[def_hwport_aes_block_size]; if (len == 0) return; memcpy(J0inc, J0, def_hwport_aes_block_size); bigint_increment((void *)(&J0inc[def_hwport_aes_block_size - sizeof(uint32_t)]), (size_t)sizeof(uint32_t)); aes_gctr(rk, J0inc, in, len, out); }
1.2.9. AES-GCM Encrypt/Decrypt 간략 예제
#define def_hwport_aes_rounds 10 /* AES128 인 경우 10 round, AES192는 12, AES256은 14 */ #define def_hwport_aes_round_key_size \ ((1+def_hwport_aes_rounds)*def_hwport_aes_block_size) static void aes_gcm_prepare_j0( const uint8_t *iv, size_t iv_len, const uint8_t *H, uint8_t *J0) { uint8_t len_buf[16]; if (iv_len == 12) { /* Prepare block J_0 = IV || 0^31 || 1 [len(IV) = 96] */ memcpy(J0, iv, iv_len); memset(J0 + iv_len, 0, def_hwport_aes_block_size - iv_len); J0[def_hwport_aes_block_size - 1] = 0x01; } else { /* s = 128 * ceil(len(IV)/128) - len(IV) J_0 = GHASH_H(IV || 0^(s+64) || [len(IV)]_64) */ ghash_start(J0); ghash(H, iv, iv_len, J0); PUT_BE64(len_buf, 0); PUT_BE64(len_buf + 8, iv_len * 8); ghash(H, len_buf, sizeof(len_buf), J0); } } void aes_gcm_encrypt( const uint8_t *key, size_t key_len, const uint8_t *iv, size_t iv_len, const uint8_t *plain, size_t plain_len, const uint8_t *aad, size_t aad_len, uint8_t *crypt, uint8_t *tag) { uint8_t s_round_key[def_hwport_aes_round_key_size]; uint8_t H[def_hwport_aes_block_size]; uint8_t J0[def_hwport_aes_block_size]; uint8_t S[16]; make_round_key_aes((void *)(&s_round_key[0]), (const void *)key); /* Generate hash subkey H = AES_K(0^128) */ encrypt_aes_ecb(memset((void *)(&H[0]), 0, sizeof(H)), sizeof(H), (const void *)(&s_round_key[0])); aes_gcm_prepare_j0(iv, iv_len, H, J0); /* C = GCTR_K(inc_32(J_0), P) */ aes_gcm_gctr(s_round_key, J0, plain, plain_len, crypt); aes_gcm_ghash(H, aad, aad_len, crypt, plain_len, S); /* T = MSB_t(GCTR_K(J_0, S)) */ aes_gctr(s_round_key, J0, S, sizeof(S), tag); /* Return (C, T) */ } void aes_gcm_decrypt( const uint8_t *key, size_t key_len, const uint8_t *iv, size_t iv_len, const uint8_t *crypt, size_t crypt_len, const uint8_t *aad, size_t aad_len, const uint8_t *tag, uint8_t *plain) { uint8_t s_round_key[def_hwport_aes_round_key_size]; uint8_t H[def_hwport_aes_block_size]; uint8_t J0[def_hwport_aes_block_size]; uint8_t S[16], T[16]; make_round_key_aes((void *)(&s_round_key[0]), (const void *)key); /* Generate hash subkey H = AES_K(0^128) */ encrypt_aes_ecb(memset((void *)(&H[0]), 0, sizeof(H)), sizeof(H), (const void *)(&s_round_key[0])); aes_gcm_prepare_j0(iv, iv_len, H, J0); /* P = GCTR_K(inc_32(J_0), C) */ aes_gcm_gctr(s_round_key, J0, crypt, crypt_len, plain); aes_gcm_ghash(H, aad, aad_len, crypt, crypt_len, S); /* T' = MSB_t(GCTR_K(J_0, S)) */ aes_gctr(s_round_key, J0, S, sizeof(S), T); if (memcmp(tag, T, 16) != 0) { /* GCM: Tag mismatch ! */ } }
1.2.10. TLS v1.2 record AES128-GCM-SHA256 Encrypt/Decrypt 간략 예제
void test0(void) { static const unsigned char cg_key0[] = { 0xB0, 0xA5, 0xD5, 0x3B, 0x85, 0xD5, 0x40, 0x91, 0x62, 0x7D, 0x15, 0x39, 0x7A, 0x16, 0x77, 0xA9 }; static const unsigned char cg_plaintext0[] = { 0x47, 0x45, 0x54, 0x20, 0x2F, 0x20, 0x48, 0x54, 0x54, 0x50, 0x2F, 0x31, 0x2E, 0x31, 0x0D, 0x0A, 0x48, 0x6F, 0x73, 0x74, 0x3A, 0x20, 0x64, 0x65, 0x76, 0x2E, 0x6D, 0x69, 0x6E, 0x7A, 0x6B, 0x6E, 0x2E, 0x63, 0x6F, 0x6D, 0x3A, 0x38, 0x30, 0x0D, 0x0A, 0x55, 0x73, 0x65, 0x72, 0x2D, 0x41, 0x67, 0x65, 0x6E, 0x74, 0x3A, 0x20, 0x63, 0x75, 0x72, 0x6C, 0x2F, 0x37, 0x2E, 0x35, 0x38, 0x2E, 0x30, 0x0D, 0x0A, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x3A, 0x20, 0x2A, 0x2F, 0x2A, 0x0D, 0x0A, 0x0D, 0x0A }; static const unsigned char cg_salt0[] = { /* Fixed */ 0x09, 0x4A, 0x8A, 0xD4 /* SALT */ }; static const unsigned char cg_iv0[] = { 0xF4, 0xFB, 0x79, 0x4B, 0x2C, 0x5D, 0xA1, 0x9D /* IV */ }; static const unsigned char cg_icv0[] = { /* integrity check value (ICV) */ 0xDF, 0xDF, 0xB0, 0x06, 0x71, 0x4C, 0x0A ,0x50, 0xD0, 0x4F, 0xC8, 0x7E, 0x53, 0x2A, 0x84, 0x32 }; static const unsigned char cg_ciphertext_combines0[] = { /* AAD */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, /* sequence-number */ 0x17, /* record-type (application-data) */ 0x03, 0x03, /* TLS version 1.2 */ 0x00, sizeof(cg_plaintext0) + sizeof(cg_iv0) + sizeof(cg_icv0), /* length 105 bytes */ /* cipher-text */ 0x73, 0xF5, 0x48, 0xDF, 0x87, 0xAC, 0x4C, 0x51, 0xF2, 0xAD, 0x46, 0xF0, 0x29, 0xF6, 0xCF, 0xD8, 0x73, 0x2C, 0x3E, 0x64, 0x47, 0x8D, 0x08, 0x5E, 0xF9, 0x6E, 0xC3, 0x9E, 0x49, 0xD2, 0xA7, 0xCD, 0xC1, 0x92, 0x4A, 0xE2, 0xD1, 0xD3, 0x40, 0xDA, 0xC3, 0xC3, 0x45, 0xCD, 0x53, 0x50, 0x31, 0xFC, 0xF0, 0x45, 0xB6, 0x88, 0x7D, 0x92, 0x57, 0x4D, 0xF6, 0xEA, 0xA3, 0x23, 0xD3, 0x0B, 0x0D, 0x92, 0x0C, 0x30, 0x83, 0xE1, 0x47, 0xD3, 0xE3, 0x77, 0xF6, 0x00, 0xE1, 0x4E, 0xE6, 0x53, 0x18, 0xD7, 0x59, /* TAG */ 0xDF, 0xDF, 0xB0, 0x06, 0x71, 0x4C, 0x0A ,0x50, 0xD0, 0x4F, 0xC8, 0x7E, 0x53, 0x2A, 0x84, 0x32 /* NO-MAC */ }; unsigned char s_salt_iv0[ sizeof(cg_salt0) + sizeof(cg_iv0) ] = {0, }; unsigned char s_aad0[ 8 + 1 + 2 + 2 ] = {0, }; unsigned char s_ciphertext0[ sizeof(cg_plaintext0) ] = {0, }; unsigned char s_tag0[ 128 >> 3 ] = {0, }; unsigned char s_plaintext0[ sizeof(cg_plaintext0) ] = {0, }; ssize_t s_process_size; (void)fprintf(stdout, "* TEST TLSv1.2 record (Cipher-suite is AES128-GCM-SHA256) => Using internal impl.\n"); (void)memcpy((void *)(&s_salt_iv0[0]), (const void *)(&cg_salt0[0]), sizeof(cg_salt0)); (void)memcpy((void *)(&s_salt_iv0[sizeof(cg_salt0)]), (const void *)(&cg_iv0[0]), sizeof(cg_iv0)); /* record-sequence number */ s_aad0[0] = (unsigned char)0x00; s_aad0[1] = (unsigned char)0x00; s_aad0[2] = (unsigned char)0x00; s_aad0[3] = (unsigned char)0x00; s_aad0[4] = (unsigned char)0x00; s_aad0[5] = (unsigned char)0x00; s_aad0[6] = (unsigned char)0x00; s_aad0[7] = (unsigned char)0x01; /* record-type */ s_aad0[8] = (unsigned char)0x17; /* TLS version */ s_aad0[9] = (unsigned char)0x03; s_aad0[10] = (unsigned char)0x03; /* record-length */ s_aad0[11] = (unsigned char)(sizeof(cg_plaintext0) >> 8);; s_aad0[12] = (unsigned char)(sizeof(cg_plaintext0) & ((size_t)0xffu));; (void)fprintf(stdout, " - TEST-VECTOR:Key (%lu bytes)\n", (unsigned long)sizeof(cg_key0)); (void)hexdump(" ", (const void *)(&cg_key0[0]), sizeof(cg_key0)); (void)fprintf(stdout, " - TEST-VECTOR:Plain-Text (%lu bytes)\n", (unsigned long)sizeof(cg_plaintext0)); (void)hexdump(" ", (const void *)(&cg_plaintext0[0]), sizeof(cg_plaintext0)); (void)fprintf(stdout, " - TEST-VECTOR:Additional-Authenticated-Data (%lu bytes)\n", (unsigned long)sizeof(s_aad0)); (void)hexdump(" ", (const void *)(&s_aad0[0]), sizeof(s_aad0)); (void)fprintf(stdout, " - TEST-VECTOR:Salt (%lu bytes)\n", (unsigned long)sizeof(cg_salt0)); (void)hexdump(" ", (const void *)(&cg_salt0[0]), sizeof(cg_salt0)); (void)fprintf(stdout, " - TEST-VECTOR:Initial-Vector (%lu bytes)\n", (unsigned long)sizeof(cg_iv0)); (void)hexdump(" ", (const void *)(&cg_iv0[0]), sizeof(cg_iv0)); (void)fprintf(stdout, " - TEST-VECTOR:Salt+IV (%lu bytes)\n", (unsigned long)sizeof(s_salt_iv0)); (void)hexdump(" ", (const void *)(&s_salt_iv0[0]), sizeof(s_salt_iv0)); (void)fprintf(stdout, " - TEST-VECTOR:Integrity-Check-Value (%lu bytes)\n", (unsigned long)sizeof(cg_icv0)); (void)hexdump(" ", (const void *)(&cg_icv0[0]), sizeof(cg_icv0)); (void)fprintf(stdout, " - TEST-VECTOR:Cipher-Text-Combines (%lu bytes)\n", (unsigned long)sizeof(cg_ciphertext_combines0)); (void)hexdump(" ", (const void *)(&cg_ciphertext_combines0[0]), sizeof(cg_ciphertext_combines0)); (void)fprintf(stdout, " - Encrypt\n"); s_process_size = (ssize_t)aes_gcm_encrypt( (const uint8_t *)(&cg_key0[0]), sizeof(cg_key0), (const uint8_t *)(&s_salt_iv0[0]), sizeof(s_salt_iv0), (const uint8_t *)(&cg_plaintext0[0]), sizeof(cg_plaintext0), (const uint8_t *)(&s_aad0[0]), sizeof(s_aad0), (uint8_t *)(&s_ciphertext0[0]), (uint8_t *)(&s_tag0[0]) ); if(s_process_size == ((ssize_t)(-1))) { (void)fprintf(stderr, "encrypt_AES_GCM failed !\n"); } else { s_process_size = (ssize_t)sizeof(cg_plaintext0); (void)fprintf(stdout, " - encrypted size : %ld\n", (long)s_process_size); /* TLS record length update */ s_aad0[11] = (unsigned char)((sizeof(cg_plaintext0) + sizeof(cg_iv0) + sizeof(cg_icv0)) >> 8);; s_aad0[12] = (unsigned char)((sizeof(cg_plaintext0) + sizeof(cg_iv0) + sizeof(cg_icv0)) & ((size_t)0xffu));; (void)hexdump(" [H] ", (const void *)(&s_aad0[0]), sizeof(s_aad0)); (void)hexdump(" [I] ", (const void *)(&cg_iv0[0]), sizeof(cg_iv0)); (void)hexdump(" [E] ", (const void *)(&s_ciphertext0[0]), (size_t)s_process_size); (void)hexdump(" [T] ", (const void *)(&s_tag0[0]), sizeof(s_tag0)); (void)fprintf( stdout, " - verify TLS header : %s\n", (memcmp( (const void *)(&s_aad0[0]), (const void *)(&cg_ciphertext_combines0[0]), sizeof(s_aad0)) == 0) ? "PASSED" : "FAILED" ); (void)fprintf( stdout, " - verify cipher-text : %s\n", (memcmp( (const void *)(&s_ciphertext0[0]), (const void *)(&cg_ciphertext_combines0[sizeof(s_aad0)]), sizeof(cg_plaintext0)) == 0) ? "PASSED" : "FAILED" ); (void)fprintf( stdout, " - verify tag : %s\n", (memcmp( (const void *)(&s_tag0[0]), (const void *)(&cg_icv0[0]), sizeof(cg_icv0)) == 0) ? "PASSED" : "FAILED" ); (void)fprintf(stdout, " - Decrypt\n"); s_aad0[11] = (unsigned char)(sizeof(cg_plaintext0) >> 8);; s_aad0[12] = (unsigned char)(sizeof(cg_plaintext0) & ((size_t)0xffu));; s_process_size = (ssize_t)aes_gcm_decrypt( (const uint8_t *)(&cg_key0[0]), sizeof(cg_key0), (const uint8_t *)(&s_salt_iv0[0]), sizeof(s_salt_iv0), (const uint8_t *)(&s_ciphertext0[0]), sizeof(s_ciphertext0), (const uint8_t *)(&s_aad0[0]), sizeof(s_aad0), (const uint8_t *)(&s_tag0[0]), (uint8_t *)(&s_plaintext0[0]) ); if(s_process_size == ((ssize_t)(-1))) { (void)fprintf(stderr, "decrypt_AES_GCM failed !\n"); } else { s_process_size = (ssize_t)sizeof(s_ciphertext0); (void)fprintf(stdout, " - decrypted size : %ld\n", (long)s_process_size); (void)hexdump(" [D] ", (const void *)(&s_plaintext0[0]), (size_t)s_process_size); (void)fprintf( stdout, " - verify cipher-text : %s\n", (memcmp( (const void *)(&s_plaintext0[0]), (const void *)(&cg_plaintext0[0]), sizeof(cg_plaintext0)) == 0) ? "PASSED" : "FAILED" ); } } }
1.3. 기초 Test Vector
1.3.1. SHA256/HMAC-SHA256 Test Vector
- TEST Digest SHA-256 push "Hello" (5 bytes)
-
00000000 18 5F 8D B3 22 71 FE 25 | F5 61 A6 FC 93 8B 2E 26 [._.."q.%.a.....&] 00000010 43 06 EC 30 4E DA 51 80 | 07 D1 76 48 26 38 19 69 [C..0N.Q...vH&8.i]
-
- TEST Digest SHA-256 simple "Hello" (5 bytes, PASSED)
-
00000000 18 5F 8D B3 22 71 FE 25 | F5 61 A6 FC 93 8B 2E 26 [._.."q.%.a.....&] 00000010 43 06 EC 30 4E DA 51 80 | 07 D1 76 48 26 38 19 69 [C..0N.Q...vH&8.i]
-
- TEST Digest HMAC-SHA-256 push (secret="", data="", PASSED)
-
00000000 B6 13 67 9A 08 14 D9 EC | 77 2F 95 D7 78 C3 5F C5 [..g.....w/..x._.] 00000010 FF 16 97 C4 93 71 56 53 | C6 C7 12 14 42 92 C5 AD [.....qVS....B...]
-
- TEST Digest HMAC-SHA-256 push (secret="key", data="The quick brown fox jumps over the lazy dog", PASSED)
-
00000000 F7 BC 83 F4 30 53 84 24 | B1 32 98 E6 AA 6F B1 43 [....0S.$.2...o.C] 00000010 EF 4D 59 A1 49 46 17 59 | 97 47 9D BC 2D 1A 3C D8 [.MY.IF.Y.G..-.<.]
-
1.3.2. TLS v1.2 PRF(Psudo Random Function) Test Vector
- TEST TLS v1.2 PRF(Psudo Random Function) (label="test label", 100 bytes)
-
00000000 E3 F2 29 BA 72 7B E1 7B | 8D 12 26 20 55 7C D4 53 [..).r{.{..& U|.S] 00000010 C2 AA B2 1D 07 C3 D4 95 | 32 9B 52 D4 E6 1E DB 5A [........2.R....Z] 00000020 6B 30 17 91 E9 0D 35 C9 | C9 A4 6B 4E 14 BA F9 AF [k0....5...kN....] 00000030 0F A0 22 F7 07 7D EF 17 | AB FD 37 97 C0 56 4B AB [.."..}....7..VK.] 00000040 4F BC 91 66 6E 9D EF 9B | 97 FC E3 4F 79 67 89 BA [O..fn......Oyg..] 00000050 A4 80 82 D1 22 EE 42 C5 | A7 2E 5A 51 10 FF F7 01 [....".B...ZQ....] 00000060 87 34 7B 66 [.4{f ]
-
1.3.3. AEAD-AES128-GCM Test Vector
- TEST AEAD-AES128-GCM
- TEST-VECTOR:Key (16 bytes)
-
00000000 88 EE 08 7F D9 5D A9 FB | F6 72 5A A9 D7 57 B0 CD [.....]...rZ..W..]
-
- TEST-VECTOR:Plain-Text (평문, 63 bytes)
-
00000000 08 00 0F 10 11 12 13 14 | 15 16 17 18 19 1A 1B 1C [................] 00000010 1D 1E 1F 20 21 22 23 24 | 25 26 27 28 29 2A 2B 2C [... !"#$%&'()*+,] 00000020 2D 2E 2F 30 31 32 33 34 | 35 36 37 38 39 3A 3B 3C [-./0123456789:;<] 00000030 3D 3E 3F 40 41 42 43 44 | 45 46 47 48 49 00 08 [=>?@ABCDEFGHI.. ]
-
- TEST-VECTOR:Additional-Authenticated-Data (20 bytes)
-
00000000 68 F2 E7 76 96 CE 7A E8 | E2 CA 4E C5 88 E5 4D 00 [h..v..z...N...M.] 00000010 2E 58 49 5C [.XI\ ]
-
- TEST-VECTOR:Initial-Vector (12 bytes)
-
00000000 7A E8 E2 CA 4E C5 00 01 | 2E 58 49 5C [z...N....XI\ ]
-
- TEST-VECTOR:Integrity-Check-Value (16 bytes)
-
00000000 88 F8 75 7A DB 8A A7 88 | D8 F6 5A D6 68 BE 70 E7 [..uz......Z.h.p.]
-
- TEST-VECTOR:Cipher-Text-Combines (99 bytes)
-
00000000 68 F2 E7 76 96 CE 7A E8 | E2 CA 4E C5 88 E5 4D 00 [h..v..z...N...M.] 00000010 2E 58 49 5C C3 1F 53 D9 | 9E 56 87 F7 36 51 19 B8 [.XI\..S..V..6Q..] 00000020 32 D2 AA E7 07 41 D5 93 | F1 F9 E2 AB 34 55 77 9B [2....A......4Uw.] 00000030 07 8E B8 FE AC DF EC 1F | 8E 3E 52 77 F8 18 0B 43 [.........>Rw...C] 00000040 36 1F 65 12 AD B1 6D 2E | 38 54 8A 2C 71 9D BA 72 [6.e...m.8T.,q..r] 00000050 28 D8 40 88 F8 75 7A DB | 8A A7 88 D8 F6 5A D6 68 [(.@..uz......Z.h] 00000060 BE 70 E7 [.p. ]
-
- Encrypt (암호문)
- encrypted size : 63
-
[A] 00000000 68 F2 E7 76 96 CE 7A E8 | E2 CA 4E C5 88 E5 4D 00 [h..v..z...N...M.] [A] 00000010 2E 58 49 5C [.XI\ ] [E] 00000000 C3 1F 53 D9 9E 56 87 F7 | 36 51 19 B8 32 D2 AA E7 [..S..V..6Q..2...] [E] 00000010 07 41 D5 93 F1 F9 E2 AB | 34 55 77 9B 07 8E B8 FE [.A......4Uw.....] [E] 00000020 AC DF EC 1F 8E 3E 52 77 | F8 18 0B 43 36 1F 65 12 [.....>Rw...C6.e.] [E] 00000030 AD B1 6D 2E 38 54 8A 2C | 71 9D BA 72 28 D8 40 [..m.8T.,q..r(.@ ] [T] 00000000 88 F8 75 7A DB 8A A7 88 | D8 F6 5A D6 68 BE 70 E7 [..uz......Z.h.p.]
-
- encrypted size : 63
- Decrypt (복호문)
- decrypted size : 63
-
[D] 00000000 08 00 0F 10 11 12 13 14 | 15 16 17 18 19 1A 1B 1C [................] [D] 00000010 1D 1E 1F 20 21 22 23 24 | 25 26 27 28 29 2A 2B 2C [... !"#$%&'()*+,] [D] 00000020 2D 2E 2F 30 31 32 33 34 | 35 36 37 38 39 3A 3B 3C [-./0123456789:;<] [D] 00000030 3D 3E 3F 40 41 42 43 44 | 45 46 47 48 49 00 08 [=>?@ABCDEFGHI.. ]
-
- decrypted size : 63
- TEST-VECTOR:Key (16 bytes)
1.4. TLS v1.2 record 분석 및 검증
1.4.1. Test Vector 산출을 위한 임의의 TLS record capture 내용 (분석 기초자료)
- HTTP Request 평문
-
00000000 47 45 54 20 2F 20 48 54 | 54 50 2F 31 2E 31 0D 0A [GET / HTTP/1.1..] 00000010 48 6F 73 74 3A 20 64 65 | 76 2E 6D 69 6E 7A 6B 6E [Host: dev.minzkn] 00000020 2E 63 6F 6D 3A 38 30 0D | 0A 55 73 65 72 2D 41 67 [.com:80..User-Ag] 00000030 65 6E 74 3A 20 63 75 72 | 6C 2F 37 2E 35 38 2E 30 [ent: curl/7.58.0] 00000040 0D 0A 41 63 63 65 70 74 | 3A 20 2A 2F 2A 0D 0A 0D [..Accept: */*...] 00000050 0A [. ]
-
- TLSv1.2 record (TLS Header + 암호문 + Tag)
-
0000 17 03 03 00 69 4b 00 2f 71 4c fe b9 77 32 8a 6f 0010 bc d1 79 7e a4 dd 90 6f f0 d1 5f 12 c2 51 6d d0 0020 c9 93 01 ec ef 57 6b 0d 79 37 7b e4 79 0f e0 6f 0030 a1 e7 8c 53 06 cf 91 d5 ca f2 0f e5 c7 88 72 f4 0040 db 69 16 39 00 82 94 5f 30 fc 81 2d cb 3d 62 65 0050 aa 53 ad 54 4e c9 01 92 ea e6 92 32 33 fc b8 39 0060 8a f6 bb 17 98 fb 8f 65 d4 4a 32 e9 94 ef
-
- Request TLSv1.2 record
- Client-Random (32/32 bytes)
-
00000000 4F 87 34 3A 2A 2A 98 B6 | BA CD 0E 44 29 7F F0 84 [O.4:**.....D)...] 00000010 16 8D 01 9F 3B 45 7E 81 | 2B 91 49 27 53 F6 03 DC [....;E~.+.I'S...]
-
- Server-Random (32/32 bytes)
-
00000000 5B F7 84 E0 F1 E5 51 7D | 75 D0 BB 61 CA 10 90 23 [[.....Q}u..a...#] 00000010 7B 92 57 34 17 12 7D BE | 44 4F 57 4E 47 52 44 01 [{.W4..}.DOWNGRD.]
-
- Master-Key(Master-Secret) (48/48 bytes)
-
00000000 BD 47 7F 8C 20 D8 FF 8E | 6A 0E F1 96 B6 05 50 8E [.G.. ...j.....P.] 00000010 9A 02 A9 8B 3E 3D 88 2D | CE 23 7F 72 50 7F EC 47 [....>=.-.#.rP..G] 00000020 D9 8A CA E6 29 17 C7 B7 | 12 58 75 DD 7B E9 71 24 [....)....Xu.{.q$]
-
- Key-Block (label="key expansion", 56 bytes)
-
00000000 A0 F7 E5 0A D2 15 EF BD | B6 39 89 2A 09 08 BD 74 [.........9.*...t] 00000010 4F 50 D1 6C C2 A4 5A F6 | 26 86 94 67 CB 54 3F 8E [OP.l..Z.&..g.T?.] 00000020 39 22 D0 86 77 D1 7C FB | C8 6C 33 F5 D5 FA 39 92 [9"..w.|..l3...9.] 00000030 08 67 0F 1F B7 F4 80 AE [.g...... ]
-
- Dump crypto_info - client, for encrypt
- version : 00000303H
- cipher_type : 51
- iv (8 bytes)
-
00000000 4B 00 2F 71 4C FE B9 77 [K./qL..w ]
-
- key (16 bytes)
-
00000000 A0 F7 E5 0A D2 15 EF BD | B6 39 89 2A 09 08 BD 74 [.........9.*...t]
-
- salt (4 bytes)
-
00000000 39 22 D0 86 [9".. ]
-
- rec_seq (8 bytes)
-
00000000 00 00 00 00 00 00 00 01 [........ ]
-
- Client-Random (32/32 bytes)
- HTTP Response 평문
-
00000000 48 54 54 50 2F 31 2E 31 | 20 34 30 33 20 46 6F 72 [HTTP/1.1 403 For] 00000010 62 69 64 64 65 6E 0D 0A | 53 65 72 76 65 72 3A 20 [bidden..Server: ] 00000020 63 6C 6F 75 64 66 6C 61 | 72 65 0D 0A 44 61 74 65 [cloudflare..Date] 00000030 3A 20 46 72 69 2C 20 32 | 33 20 4E 6F 76 20 32 30 [: Fri, 23 Nov 20] 00000040 31 38 20 30 34 3A 34 31 | 3A 30 34 20 47 4D 54 0D [18 04:41:04 GMT.] 00000050 0A 43 6F 6E 74 65 6E 74 | 2D 54 79 70 65 3A 20 74 [.Content-Type: t] 00000060 65 78 74 2F 68 74 6D 6C | 0D 0A 43 6F 6E 74 65 6E [ext/html..Conten] 00000070 74 2D 4C 65 6E 67 74 68 | 3A 20 31 36 37 0D 0A 43 [t-Length: 167..C] 00000080 6F 6E 6E 65 63 74 69 6F | 6E 3A 20 6B 65 65 70 2D [onnection: keep-] 00000090 61 6C 69 76 65 0D 0A 43 | 46 2D 52 41 59 3A 20 34 [alive..CF-RAY: 4] 000000A0 37 65 30 66 36 31 64 35 | 61 37 32 61 32 32 64 2D [7e0f61d5a72a22d-] 000000B0 49 43 4E 0D 0A 0D 0A 3C | 68 74 6D 6C 3E 0D 0A 3C [ICN....<html>..<] 000000C0 68 65 61 64 3E 3C 74 69 | 74 6C 65 3E 34 30 33 20 [head><title>403 ] 000000D0 46 6F 72 62 69 64 64 65 | 6E 3C 2F 74 69 74 6C 65 [Forbidden</title] 000000E0 3E 3C 2F 68 65 61 64 3E | 0D 0A 3C 62 6F 64 79 20 [></head>..<body ] 000000F0 62 67 63 6F 6C 6F 72 3D | 22 77 68 69 74 65 22 3E [bgcolor="white">] 00000100 0D 0A 3C 63 65 6E 74 65 | 72 3E 3C 68 31 3E 34 30 [..<center><h1>40] 00000110 33 20 46 6F 72 62 69 64 | 64 65 6E 3C 2F 68 31 3E [3 Forbidden</h1>] 00000120 3C 2F 63 65 6E 74 65 72 | 3E 0D 0A 3C 68 72 3E 3C [</center>..<hr><] 00000130 63 65 6E 74 65 72 3E 63 | 6C 6F 75 64 66 6C 61 72 [center>cloudflar] 00000140 65 3C 2F 63 65 6E 74 65 | 72 3E 0D 0A 3C 2F 62 6F [e</center>..</bo] 00000150 64 79 3E 0D 0A 3C 2F 68 | 74 6D 6C 3E 0D 0A [dy>..</html>.. ]
-
- TLSv1.2 record (TLS Header + 암호문 + Tag)
-
0000 17 03 03 01 76 d1 a5 f4 96 f7 8b fa 4d c2 92 d0 0010 b3 f2 be 59 b0 54 f4 55 8e e1 a1 54 23 2c 15 af 0020 bd bc 0a 3f 40 dd 83 d9 dc b1 58 d8 4e 74 eb 4e 0030 23 aa cf 74 4c 4f 5b 95 ad 31 1a 4c 00 83 3e 1b 0040 32 9f a9 6f 89 22 52 ee 90 4c 79 60 16 eb e3 aa 0050 7e 44 58 8a e1 4b 95 30 8b de fe 7c 77 bd e7 2c 0060 62 00 d8 a0 9e 12 47 40 76 56 7c 93 2e a3 c0 ba 0070 49 0f c6 1d cd 39 ce 79 c9 fd c4 94 dc 67 1f 3b 0080 4f bd 81 3f 5d 8f 2d 5a 9d a4 f1 99 fd 69 22 85 0090 0a 55 d7 9e 66 8b fd 32 7c 3f 1a 22 45 30 5b c4 00a0 ac ba 15 7e 0a 7b 25 51 1f 5a 84 4c 47 e1 34 5d 00b0 e6 96 1b fc f8 6e eb 8e 36 c8 fa 2f 7f dd 32 91 00c0 e6 5e 1e 76 fe a3 a6 63 1f d4 00 d5 84 cb 98 af 00d0 34 69 62 9c 95 36 86 72 17 58 48 00 0c e8 54 64 00e0 11 2f 04 4f ad a4 19 24 48 ab 37 24 2b 05 3f a8 00f0 0a c5 8b 76 77 73 fc 04 71 a7 d9 17 df 42 55 a1 0100 19 50 26 d4 0f f3 1b df 71 a7 84 08 bd e5 8a 03 0110 b7 d3 1e bc 4b 9b 2b a2 71 ed c4 be 65 95 90 5e 0120 31 a2 15 35 b1 f7 d5 e5 5a 0b 32 ee 3e dc c6 1a 0130 ec 07 cf 6e fa a1 00 d1 e9 f0 ba 52 de 8a cd 17 0140 26 52 00 5c 79 97 35 1f 20 5e 92 5c 97 d4 cf ea 0150 4e 26 04 dd 09 81 d6 ca 9a 5a a6 86 4d 54 f7 aa 0160 dd ee 98 c5 d8 13 b6 77 73 f5 13 f4 50 4e c4 c6 0170 4c ef 9d 96 10 24 e7 6a b0 d3 8e
-
- Response TLSv1.2 record
- Client-Random (32/32 bytes)
-
00000000 06 D8 99 31 1D C8 78 88 | 86 0F B8 87 AA 2F 07 A3 [...1..x....../..] 00000010 05 D6 F7 A1 58 B8 1B 97 | 91 A5 44 A4 5E 08 9F 10 [....X.....D.^...]
-
- Server-Random (32/32 bytes)
-
00000000 FB CD 81 02 9B 7B 21 AC | 6E 3B B5 07 54 12 D2 70 [.....{!.n;..T..p] 00000010 08 61 A2 E6 CD 9F 7E F5 | 13 89 2C 9F 36 80 13 D1 [.a....~...,.6...]
-
- Master-Key(Master-Secret) (48/48 bytes)
-
00000000 57 40 CF 59 50 5F 14 1C | A9 3F 36 81 61 EF 76 32 [W@.YP_...?6.a.v2] 00000010 83 63 34 61 A8 F2 5E B9 | 1A 4E 3A 24 14 1B 77 E2 [.c4a..^..N:$..w.] 00000020 13 3B D1 99 1D 7F D3 F9 | 74 DC A3 0A 71 9C 0B 99 [.;......t...q...]
-
- Key-Block (label="key expansion", 56 bytes)
-
00000000 52 35 8F 10 8C B2 64 46 | B9 86 8A C7 7E 0A EE A5 [R5....dF....~...] 00000010 8D 30 5F D0 42 7D C4 17 | 1F AC 48 C8 BC 23 96 D0 [.0_.B}....H..#..] 00000020 78 A4 09 5A 20 5B 93 AE | 8B 27 D5 0E F1 83 A9 DD [x..Z [...'......] 00000030 96 E0 5E D9 08 C2 5C DF [..^...\. ]
-
- Dump crypto_info - server, for encrypt
- version : 00000303H
- cipher_type : 51
- iv (8 bytes)
-
00000000 D1 A5 F4 96 F7 8B FA 4D [.......M ]
-
- key (16 bytes)
-
00000000 8D 30 5F D0 42 7D C4 17 | 1F AC 48 C8 BC 23 96 D0 [.0_.B}....H..#..]
-
- salt (4 bytes)
-
00000000 20 5B 93 AE [ [.. ]
-
- rec_seq (8 bytes)
-
00000000 00 00 00 00 00 00 00 01 [........ ]
-
- Client-Random (32/32 bytes)
1.4.2. TLS record capture 내용 (분석 기초자료) Test Vector 산출정리
- TEST TLSv1.2 record (Cipher-suite is AES128-GCM-SHA256)
- TEST-VECTOR:Key (16 bytes)
-
00000000 B0 A5 D5 3B 85 D5 40 91 | 62 7D 15 39 7A 16 77 A9 [...;..@.b}.9z.w.]
-
- TEST-VECTOR:Plain-Text (81 bytes)
-
00000000 47 45 54 20 2F 20 48 54 | 54 50 2F 31 2E 31 0D 0A [GET / HTTP/1.1..] 00000010 48 6F 73 74 3A 20 64 65 | 76 2E 6D 69 6E 7A 6B 6E [Host: dev.minzkn] 00000020 2E 63 6F 6D 3A 38 30 0D | 0A 55 73 65 72 2D 41 67 [.com:80..User-Ag] 00000030 65 6E 74 3A 20 63 75 72 | 6C 2F 37 2E 35 38 2E 30 [ent: curl/7.58.0] 00000040 0D 0A 41 63 63 65 70 74 | 3A 20 2A 2F 2A 0D 0A 0D [..Accept: */*...] 00000050 0A [. ]
-
- TEST-VECTOR:Additional-Authenticated-Data (13 bytes)
-
00000000 00 00 00 00 00 00 00 01 | 17 03 03 00 51 [............Q ]
-
- TEST-VECTOR:Salt (4 bytes)
-
00000000 09 4A 8A D4 [.J.. ]
-
- TEST-VECTOR:Initial-Vector (8 bytes)
-
00000000 F4 FB 79 4B 2C 5D A1 9D [..yK,].. ]
-
- TEST-VECTOR:Salt+IV (12 bytes)
-
00000000 09 4A 8A D4 F4 FB 79 4B | 2C 5D A1 9D [.J....yK,].. ]
-
- TEST-VECTOR:Integrity-Check-Value (16 bytes)
-
00000000 DF DF B0 06 71 4C 0A 50 | D0 4F C8 7E 53 2A 84 32 [....qL.P.O.~S*.2]
-
- TEST-VECTOR:Cipher-Text-Combines (110 bytes)
-
00000000 00 00 00 00 00 00 00 01 | 17 03 03 00 69 73 F5 48 [............is.H] 00000010 DF 87 AC 4C 51 F2 AD 46 | F0 29 F6 CF D8 73 2C 3E [...LQ..F.)...s,>] 00000020 64 47 8D 08 5E F9 6E C3 | 9E 49 D2 A7 CD C1 92 4A [dG..^.n..I.....J] 00000030 E2 D1 D3 40 DA C3 C3 45 | CD 53 50 31 FC F0 45 B6 [...@...E.SP1..E.] 00000040 88 7D 92 57 4D F6 EA A3 | 23 D3 0B 0D 92 0C 30 83 [.}.WM...#.....0.] 00000050 E1 47 D3 E3 77 F6 00 E1 | 4E E6 53 18 D7 59 DF DF [.G..w...N.S..Y..] 00000060 B0 06 71 4C 0A 50 D0 4F | C8 7E 53 2A 84 32 [..qL.P.O.~S*.2 ]
-
- Encrypt
- encrypted size : 81
-
[H] 00000000 00 00 00 00 00 00 00 01 | 17 03 03 00 69 [............i ] [I] 00000000 F4 FB 79 4B 2C 5D A1 9D [..yK,].. ] [E] 00000000 73 F5 48 DF 87 AC 4C 51 | F2 AD 46 F0 29 F6 CF D8 [s.H...LQ..F.)...] [E] 00000010 73 2C 3E 64 47 8D 08 5E | F9 6E C3 9E 49 D2 A7 CD [s,>dG..^.n..I...] [E] 00000020 C1 92 4A E2 D1 D3 40 DA | C3 C3 45 CD 53 50 31 FC [..J...@...E.SP1.] [E] 00000030 F0 45 B6 88 7D 92 57 4D | F6 EA A3 23 D3 0B 0D 92 [.E..}.WM...#....] [E] 00000040 0C 30 83 E1 47 D3 E3 77 | F6 00 E1 4E E6 53 18 D7 [.0..G..w...N.S..] [E] 00000050 59 [Y ] [T] 00000000 DF DF B0 06 71 4C 0A 50 | D0 4F C8 7E 53 2A 84 32 [....qL.P.O.~S*.2]
-
- encrypted size : 81
- Decrypt
- decrypted size : 81
-
[D] 00000000 47 45 54 20 2F 20 48 54 | 54 50 2F 31 2E 31 0D 0A [GET / HTTP/1.1..] [D] 00000010 48 6F 73 74 3A 20 64 65 | 76 2E 6D 69 6E 7A 6B 6E [Host: dev.minzkn] [D] 00000020 2E 63 6F 6D 3A 38 30 0D | 0A 55 73 65 72 2D 41 67 [.com:80..User-Ag] [D] 00000030 65 6E 74 3A 20 63 75 72 | 6C 2F 37 2E 35 38 2E 30 [ent: curl/7.58.0] [D] 00000040 0D 0A 41 63 63 65 70 74 | 3A 20 2A 2F 2A 0D 0A 0D [..Accept: */*...] [D] 00000050 0A [. ]
-
- decrypted size : 81
- TEST-VECTOR:Key (16 bytes)
1.4.3. Linux kernel 3.x 기준 crypto API 를 이용한 검증 코드의 구현
Linux kernel 3.x 기준으로 검증코드를 작성하였으나 4.x 기준의 경우 ADD 를 다루는 부분만 차이가 있으며 나머지는 거의 비슷하여 쉽게 포팅 가능하다는 점. Linux kernel의 crypto API는 굉장히 잘 만들었다는 점 실감하면서...
static void test_crypto_aead_done(struct crypto_async_request *req, int err) { (void)req; (void)err; } static ssize_t test_crypto_encrypt_AEAD( const char *s_alg_name, const void *s_plaintext, size_t s_plaintext_size, const void *s_aad, size_t s_aad_size, const void *s_key, size_t s_key_size, const void *s_salt, size_t s_salt_size, const void *s_iv, size_t s_iv_size, void *s_ciphertext, size_t s_ciphertext_size, void *s_tag, size_t s_tag_size ) { static const char cg_default_alg_name[] = {"gcm(aes)"}; ssize_t s_result; size_t s_temp_offset; uint8_t s_temp_buffer[ 128 ]; struct crypto_aead *tfm; struct aead_request *req; struct scatterlist s_sg_plaintext[1] ; struct scatterlist s_sg_ciphertext[ 1 /* ciphertext */ + 1 /* tag */ ]; struct scatterlist s_sg_gmactext[1]; int s_check; if(unlikely(s_alg_name == ((const char *)0))) { s_alg_name = (const char *)(&cg_default_alg_name[0]); } /* struct crypto_aead *crypto_alloc_aead(const char *alg_name, u32 type, u32 mask) */ tfm = crypto_alloc_aead(s_alg_name, (u32)0u, (u32)0u); if(IS_ERR(tfm)) { printk(KERN_WARNING "crypto_alloc_aead failed ! (tfm=%p, alg_name=\"%s\")\n", tfm, s_alg_name); s_result = (ssize_t)(-1); goto l_return0; } #if 0L /* DEBUG : algorithm specification info */ /* static inline unsigned int crypto_aead_authsize(struct crypto_aead *tfm) */ printk(KERN_INFO " - AEAD authsize (%u bytes)\n", crypto_aead_authsize(tfm)); /* static inline unsigned int crypto_aead_ivsize(struct crypto_aead *tfm) */ printk(KERN_INFO " - AEAD ivsize (%u bytes)\n", crypto_aead_ivsize(tfm)); /* static inline unsigned int crypto_aead_blocksize(struct crypto_aead *tfm) */ printk(KERN_INFO " - AEAD blocksize (%u bytes)\n", crypto_aead_blocksize(tfm)); #endif /* static inline struct aead_request *aead_request_alloc(struct crypto_aead *tfm, gfp_t gfp) */ req = aead_request_alloc(tfm, GFP_KERNEL); if(IS_ERR(req)) { printk(KERN_WARNING "aead_request_alloc failed ! (req=%p, alg_name=\"%s\")\n", req, s_alg_name); s_result = (ssize_t)(-1); goto l_return1; } /* static inline void aead_request_set_callback(struct aead_request *req, u32 flags, crypto_completion_t complete, void *data) */ aead_request_set_callback( req, CRYPTO_TFM_REQ_MAY_BACKLOG, test_crypto_aead_done, (void *)0 ); /* static inline void crypto_aead_clear_flags(struct crypto_aead *tfm, u32 flags) */ crypto_aead_clear_flags(tfm, ~((u32)0u)); /* static inline int crypto_aead_setkey(struct crypto_aead *tfm, const u8 *key, unsigned int keylen) */ s_check = crypto_aead_setkey( tfm, (const u8 *)s_key, (unsigned int)s_key_size ); if(unlikely(s_check != 0)) { printk(KERN_WARNING "crypto_aead_setkey failed ! (check=%d, alg_name=\"%s\", key-size=%lu)\n", s_check, s_alg_name, (unsigned long)s_key_size); s_result = (ssize_t)(-1); goto l_return2; } /* This is the Integrity Check Value (aka the authentication tag length and can be 8, 12 or 16 bytes long. */ /* Assuming we are supporting rfc4106 64-bit extended sequence numbers We need to have the AAD length equal to 8 or 12 bytes */ /* int crypto_aead_setauthsize(struct crypto_aead *tfm, unsigned int authsize); */ s_check = crypto_aead_setauthsize(tfm, (unsigned int)s_tag_size); if(unlikely(s_check != 0)) { printk(KERN_WARNING "crypto_aead_setauthsize failed ! (check=%d, alg_name=\"%s\", tag-size=%lu)\n", s_check, s_alg_name, (unsigned long)s_tag_size); s_result = (ssize_t)(-1); goto l_return2; } /* plaintext to scatterlist */ sg_init_table(&s_sg_plaintext[0], sizeof(s_sg_plaintext) / sizeof(struct scatterlist)); sg_set_buf(&s_sg_plaintext[0], s_plaintext, s_plaintext_size); /* IN: plaintext */ /* ciphertext to scatterlist */ sg_init_table(&s_sg_ciphertext[0], sizeof(s_sg_ciphertext) / sizeof(struct scatterlist)); sg_set_buf(&s_sg_ciphertext[0], s_ciphertext, s_ciphertext_size); /* OUT: ciphertext */ sg_set_buf(&s_sg_ciphertext[1], s_tag, s_tag_size); /* OUT: tag */ s_temp_offset = (size_t)0u; (void)memcpy((void *)(&s_temp_buffer[s_temp_offset]), s_salt, s_salt_size); s_temp_offset += s_salt_size; (void)memcpy((void *)(&s_temp_buffer[s_temp_offset]), s_iv, s_iv_size); s_temp_offset += s_iv_size; /* static inline void aead_request_set_crypt(struct aead_request *req, struct scatterlist *src, struct scatterlist *dst, unsigned int cryptlen, u8 *iv) */ aead_request_set_crypt( req, (struct scatterlist *)(&s_sg_plaintext[0]), (struct scatterlist *)(&s_sg_ciphertext[0]), (unsigned int)s_plaintext_size, (u8 *)(&s_temp_buffer[0]) ); sg_init_one(&s_sg_gmactext[0], s_aad, s_aad_size); /* static inline void aead_request_set_assoc(struct aead_request *req, struct scatterlist *assoc, unsigned int assoclen) */ aead_request_set_assoc( req, (struct scatterlist *)(&s_sg_gmactext[0]), (unsigned int)s_aad_size ); /* static inline int crypto_aead_encrypt(struct aead_request *req) */ s_check = crypto_aead_encrypt(req); if(unlikely(s_check != 0)) { printk(KERN_WARNING "crypto_aead_encrypt failed ! (check=%d, alg_name=\"%s\")\n", s_check, s_alg_name); s_result = (ssize_t)(-1); goto l_return2; } /* SUCCESS */ s_result = (ssize_t)s_ciphertext_size; l_return2:; /* static inline void aead_request_free(struct aead_request *req) */ aead_request_free(req); l_return1:; /* static inline void crypto_free_aead(struct crypto_aead *tfm) */ crypto_free_aead(tfm); l_return0:; return(s_result); } static int test_crypto_tlsv1_2_AES128_GCM_SHA256_encrypt(void) { static const unsigned char cg_key0[] = { 0xB0, 0xA5, 0xD5, 0x3B, 0x85, 0xD5, 0x40, 0x91, 0x62, 0x7D, 0x15, 0x39, 0x7A, 0x16, 0x77, 0xA9 }; static const unsigned char cg_plaintext0[] = { 0x47, 0x45, 0x54, 0x20, 0x2F, 0x20, 0x48, 0x54, 0x54, 0x50, 0x2F, 0x31, 0x2E, 0x31, 0x0D, 0x0A, 0x48, 0x6F, 0x73, 0x74, 0x3A, 0x20, 0x64, 0x65, 0x76, 0x2E, 0x6D, 0x69, 0x6E, 0x7A, 0x6B, 0x6E, 0x2E, 0x63, 0x6F, 0x6D, 0x3A, 0x38, 0x30, 0x0D, 0x0A, 0x55, 0x73, 0x65, 0x72, 0x2D, 0x41, 0x67, 0x65, 0x6E, 0x74, 0x3A, 0x20, 0x63, 0x75, 0x72, 0x6C, 0x2F, 0x37, 0x2E, 0x35, 0x38, 0x2E, 0x30, 0x0D, 0x0A, 0x41, 0x63, 0x63, 0x65, 0x70, 0x74, 0x3A, 0x20, 0x2A, 0x2F, 0x2A, 0x0D, 0x0A, 0x0D, 0x0A }; static const unsigned char cg_salt0[] = { /* Fixed */ 0x09, 0x4A, 0x8A, 0xD4 /* SALT */ }; static const unsigned char cg_iv0[] = { 0xF4, 0xFB, 0x79, 0x4B, 0x2C, 0x5D, 0xA1, 0x9D /* IV */ }; static const unsigned char cg_icv0[] = { /* integrity check value (ICV) */ 0xDF, 0xDF, 0xB0, 0x06, 0x71, 0x4C, 0x0A ,0x50, 0xD0, 0x4F, 0xC8, 0x7E, 0x53, 0x2A, 0x84, 0x32 }; static const unsigned char cg_ciphertext_combines0[] = { /* AAD */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, /* sequence-number */ 0x17, /* record-type (application-data) */ 0x03, 0x03, /* TLS version 1.2 */ 0x00, sizeof(cg_plaintext0) + sizeof(cg_iv0) + sizeof(cg_icv0), /* length 105 bytes */ /* cipher-text */ 0x73, 0xF5, 0x48, 0xDF, 0x87, 0xAC, 0x4C, 0x51, 0xF2, 0xAD, 0x46, 0xF0, 0x29, 0xF6, 0xCF, 0xD8, 0x73, 0x2C, 0x3E, 0x64, 0x47, 0x8D, 0x08, 0x5E, 0xF9, 0x6E, 0xC3, 0x9E, 0x49, 0xD2, 0xA7, 0xCD, 0xC1, 0x92, 0x4A, 0xE2, 0xD1, 0xD3, 0x40, 0xDA, 0xC3, 0xC3, 0x45, 0xCD, 0x53, 0x50, 0x31, 0xFC, 0xF0, 0x45, 0xB6, 0x88, 0x7D, 0x92, 0x57, 0x4D, 0xF6, 0xEA, 0xA3, 0x23, 0xD3, 0x0B, 0x0D, 0x92, 0x0C, 0x30, 0x83, 0xE1, 0x47, 0xD3, 0xE3, 0x77, 0xF6, 0x00, 0xE1, 0x4E, 0xE6, 0x53, 0x18, 0xD7, 0x59, /* TAG */ 0xDF, 0xDF, 0xB0, 0x06, 0x71, 0x4C, 0x0A ,0x50, 0xD0, 0x4F, 0xC8, 0x7E, 0x53, 0x2A, 0x84, 0x32 /* NO-MAC */ }; unsigned char s_aad0[ 8 + 1 + 2 + 2 ] = {0, }; unsigned char s_ciphertext0[ sizeof(cg_plaintext0) ] = {0, }; unsigned char s_tag0[ 128 >> 3 ] = {0, }; ssize_t s_process_size; (void)printk(KERN_INFO "* TEST TLSv1.2 record (Cipher-suite is AES128-GCM-SHA256)\n"); /* record-sequence number */ s_aad0[0] = (uint8_t)0x00u; s_aad0[1] = (uint8_t)0x00u; s_aad0[2] = (uint8_t)0x00u; s_aad0[3] = (uint8_t)0x00u; s_aad0[4] = (uint8_t)0x00u; s_aad0[5] = (uint8_t)0x00u; s_aad0[6] = (uint8_t)0x00u; s_aad0[7] = (uint8_t)0x01u; /* record type */ *((uint8_t *)(&s_aad0[8])) = (uint8_t)0x17; /* record version */ *((uint16_t *)(&s_aad0[9])) = htons(0x0303); /* record length */ *((uint16_t *)(&s_aad0[11])) = htons(sizeof(cg_plaintext0)); (void)printk(KERN_INFO " - TEST-VECTOR:Key (%lu bytes)\n", (unsigned long)sizeof(cg_key0)); print_hex_dump( KERN_INFO, " ", DUMP_PREFIX_OFFSET, 16, 1, (const void *)(&cg_key0[0]), sizeof(cg_key0), true ); (void)printk(KERN_INFO " - TEST-VECTOR:Plain-Text (%lu bytes)\n", (unsigned long)sizeof(cg_plaintext0)); print_hex_dump( KERN_INFO, " ", DUMP_PREFIX_OFFSET, 16, 1, (const void *)(&cg_plaintext0[0]), sizeof(cg_plaintext0), true ); (void)printk(KERN_INFO " - TEST-VECTOR:Additional-Authenticated-Data (%lu bytes)\n", (unsigned long)sizeof(s_aad0)); print_hex_dump( KERN_INFO, " ", DUMP_PREFIX_OFFSET, 16, 1, (const void *)(&s_aad0[0]), sizeof(s_aad0), true ); (void)printk(KERN_INFO " - TEST-VECTOR:Salt (%lu bytes)\n", (unsigned long)sizeof(cg_salt0)); print_hex_dump( KERN_INFO, " ", DUMP_PREFIX_OFFSET, 16, 1, (const void *)(&cg_salt0[0]), sizeof(cg_salt0), true ); (void)printk(KERN_INFO " - TEST-VECTOR:Initial-Vector (%lu bytes)\n", (unsigned long)sizeof(cg_iv0)); print_hex_dump( KERN_INFO, " ", DUMP_PREFIX_OFFSET, 16, 1, (const void *)(&cg_iv0[0]), sizeof(cg_iv0), true ); (void)printk(KERN_INFO " - TEST-VECTOR:Integrity-Check-Value (%lu bytes)\n", (unsigned long)sizeof(cg_icv0)); print_hex_dump( KERN_INFO, " ", DUMP_PREFIX_OFFSET, 16, 1, (const void *)(&cg_icv0[0]), sizeof(cg_icv0), true ); (void)printk(KERN_INFO " - TEST-VECTOR:Cipher-Text-Combines (%lu bytes)\n", (unsigned long)sizeof(cg_ciphertext_combines0)); print_hex_dump( KERN_INFO, " ", DUMP_PREFIX_OFFSET, 16, 1, (const void *)(&cg_ciphertext_combines0[0]), sizeof(cg_ciphertext_combines0), true ); (void)printk(KERN_INFO " - Encrypt\n"); s_process_size = test_crypto_encrypt_AEAD( "gcm(aes)", (const void *)(&cg_plaintext0[0]), sizeof(cg_plaintext0), (const void *)(&s_aad0[0]), sizeof(s_aad0), (const void *)(&cg_key0[0]), sizeof(cg_key0), (const void *)(&cg_salt0[0]), sizeof(cg_salt0), (const void *)(&cg_iv0[0]), sizeof(cg_iv0), (void *)(&s_ciphertext0[0]), sizeof(s_ciphertext0), (void *)(&s_tag0[0]), sizeof(s_tag0) ); if(s_process_size == ((ssize_t)(-1))) { (void)printk(KERN_WARNING "test_crypto_encrypt_AEAD failed !\n"); } else { (void)printk(KERN_INFO " - encrypted size : %ld\n", (long)s_process_size); /* TLS record length update */ *((uint16_t *)(&s_aad0[ 8 + 1 + 2 ])) = htons(sizeof(cg_plaintext0) + sizeof(cg_iv0) + sizeof(cg_icv0)); print_hex_dump( KERN_INFO, " [H] ", DUMP_PREFIX_OFFSET, 16, 1, (const void *)(&s_aad0[0]), sizeof(s_aad0), true ); print_hex_dump( KERN_INFO, " [I] ", DUMP_PREFIX_OFFSET, 16, 1, (const void *)(&cg_iv0[0]), sizeof(cg_iv0), true ); print_hex_dump( KERN_INFO, " [E] ", DUMP_PREFIX_OFFSET, 16, 1, (const void *)(&s_ciphertext0[0]), sizeof(s_ciphertext0), true ); print_hex_dump( KERN_INFO, " [T] ", DUMP_PREFIX_OFFSET, 16, 1, (const void *)(&s_tag0[0]), sizeof(s_tag0), true ); (void)printk( KERN_INFO " - verify TLS header : %s\n", (memcmp( (const void *)(&s_aad0[0]), (const void *)(&cg_ciphertext_combines0[0]), sizeof(s_aad0)) == 0) ? "PASSED" : "FAILED" ); (void)printk( KERN_INFO " - verify cipher-text : %s\n", (memcmp( (const void *)(&s_ciphertext0[0]), (const void *)(&cg_ciphertext_combines0[sizeof(s_aad0)]), sizeof(cg_plaintext0)) == 0) ? "PASSED" : "FAILED" ); (void)printk( KERN_INFO " - verify tag : %s\n", (memcmp( (const void *)(&s_tag0[0]), (const void *)(&cg_icv0[0]), sizeof(cg_icv0)) == 0) ? "PASSED" : "FAILED" ); } return(0); }
1.5. Test Vector 분석 및 검증 결과 (최종 정리)
Cipher suite list set : "ECDH-ECDSA-AES128-GCM-SHA256:ECDH-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES128-GCM-SHA256:DH-RSA-AES128-GCM-SHA256:RSA-PSK-AES128-GCM-SHA256:DHE-PSK-AES128-GCM-SHA256:AES128-GCM-SHA256:PSK-AES128-GCM-SHA256" Generating RSA private key ... IPv4 socket opened. Ready SSL-Inspection with kTLS ... ("[0.0.0.0]:80") Accepted (fd=6, accept-from="2.0.208.34") SSL connecting. (for fd=6, "[1.0.0.1]:443") SSL connected. (fd=7, for fd=6, "[1.0.0.1]:443") SSL Accepted (fd=6) current server-side cipher info (fd=6, "SSL negotiation finished successfully") - version : "TLSv1.2" - bits : 128 - name : "ECDHE-RSA-AES128-GCM-SHA256" - id : 50380847 - kx_nid : 1038 - auth_nid : 1046 - Is AEAD : 1 SSL-Session: Protocol : TLSv1.2 Cipher : ECDHE-RSA-AES128-GCM-SHA256 Session-ID: 4E200C15CA0779218BF6C64B1D04D48AAD4649AECBD3968F3E9B12E2F6C5C3E0 Session-ID-ctx: Master-Key: 5740CF59505F141CA93F368161EF763283633461A8F25EB91A4E3A24141B77E2133BD1991D7FD3F974DCA30A719C0B99 PSK identity: None PSK identity hint: None SRP username: None Start Time: 1542948064 Timeout : 7200 (sec) Verify return code: 0 (ok) Extended master secret: yes Client-Random (32/32 bytes) 00000000 06 D8 99 31 1D C8 78 88 | 86 0F B8 87 AA 2F 07 A3 [...1..x....../..] 00000010 05 D6 F7 A1 58 B8 1B 97 | 91 A5 44 A4 5E 08 9F 10 [....X.....D.^...] Server-Random (32/32 bytes) 00000000 FB CD 81 02 9B 7B 21 AC | 6E 3B B5 07 54 12 D2 70 [.....{!.n;..T..p] 00000010 08 61 A2 E6 CD 9F 7E F5 | 13 89 2C 9F 36 80 13 D1 [.a....~...,.6...] Master-Key(Master-Secret) (48/48 bytes) 00000000 57 40 CF 59 50 5F 14 1C | A9 3F 36 81 61 EF 76 32 [W@.YP_...?6.a.v2] 00000010 83 63 34 61 A8 F2 5E B9 | 1A 4E 3A 24 14 1B 77 E2 [.c4a..^..N:$..w.] 00000020 13 3B D1 99 1D 7F D3 F9 | 74 DC A3 0A 71 9C 0B 99 [.;......t...q...] Key-Block (label="key expansion", 56 bytes) 00000000 52 35 8F 10 8C B2 64 46 | B9 86 8A C7 7E 0A EE A5 [R5....dF....~...] 00000010 8D 30 5F D0 42 7D C4 17 | 1F AC 48 C8 BC 23 96 D0 [.0_.B}....H..#..] 00000020 78 A4 09 5A 20 5B 93 AE | 8B 27 D5 0E F1 83 A9 DD [x..Z [...'......] 00000030 96 E0 5E D9 08 C2 5C DF [..^...\. ] Dump crypto_info - server, for decrypt - version : 00000303H - cipher_type : 51 - iv (8 bytes) 00000000 1F ED AB 03 8E AE A8 D0 [........ ] - key (16 bytes) 00000000 52 35 8F 10 8C B2 64 46 | B9 86 8A C7 7E 0A EE A5 [R5....dF....~...] - salt (4 bytes) 00000000 78 A4 09 5A [x..Z ] - rec_seq (8 bytes) 00000000 00 00 00 00 00 00 00 01 [........ ] SOL_TCP/TCP_ULP(server, for decrypt) supported. (fd=6) Client-Random (32/32 bytes) 00000000 06 D8 99 31 1D C8 78 88 | 86 0F B8 87 AA 2F 07 A3 [...1..x....../..] 00000010 05 D6 F7 A1 58 B8 1B 97 | 91 A5 44 A4 5E 08 9F 10 [....X.....D.^...] Server-Random (32/32 bytes) 00000000 FB CD 81 02 9B 7B 21 AC | 6E 3B B5 07 54 12 D2 70 [.....{!.n;..T..p] 00000010 08 61 A2 E6 CD 9F 7E F5 | 13 89 2C 9F 36 80 13 D1 [.a....~...,.6...] Master-Key(Master-Secret) (48/48 bytes) 00000000 57 40 CF 59 50 5F 14 1C | A9 3F 36 81 61 EF 76 32 [W@.YP_...?6.a.v2] 00000010 83 63 34 61 A8 F2 5E B9 | 1A 4E 3A 24 14 1B 77 E2 [.c4a..^..N:$..w.] 00000020 13 3B D1 99 1D 7F D3 F9 | 74 DC A3 0A 71 9C 0B 99 [.;......t...q...] Key-Block (label="key expansion", 56 bytes) 00000000 52 35 8F 10 8C B2 64 46 | B9 86 8A C7 7E 0A EE A5 [R5....dF....~...] 00000010 8D 30 5F D0 42 7D C4 17 | 1F AC 48 C8 BC 23 96 D0 [.0_.B}....H..#..] 00000020 78 A4 09 5A 20 5B 93 AE | 8B 27 D5 0E F1 83 A9 DD [x..Z [...'......] 00000030 96 E0 5E D9 08 C2 5C DF [..^...\. ] Dump crypto_info - server, for encrypt - version : 00000303H - cipher_type : 51 - iv (8 bytes) 00000000 D1 A5 F4 96 F7 8B FA 4D [.......M ] - key (16 bytes) 00000000 8D 30 5F D0 42 7D C4 17 | 1F AC 48 C8 BC 23 96 D0 [.0_.B}....H..#..] - salt (4 bytes) 00000000 20 5B 93 AE [ [.. ] - rec_seq (8 bytes) 00000000 00 00 00 00 00 00 00 01 [........ ] SOL_TCP/TCP_ULP(server, for encrypt) supported. (fd=6) current client-side cipher info (fd=7, "SSL negotiation finished successfully") - vesion : "TLSv1.2" - bits : 128 - name : "ECDHE-ECDSA-AES128-GCM-SHA256" - id : 50380843 - kx_nid : 1038 - auth_nid : 1047 - Is AEAD : 1 SSL-Session: Protocol : TLSv1.2 Cipher : ECDHE-ECDSA-AES128-GCM-SHA256 Session-ID: 497688771B29CB8C48FFE5908CB6C0743DA95B4060D0C54DE04C4BBE2ECB158D Session-ID-ctx: Master-Key: BD477F8C20D8FF8E6A0EF196B605508E9A02A98B3E3D882DCE237F72507FEC47D98ACAE62917C7B7125875DD7BE97124 PSK identity: None PSK identity hint: None SRP username: None TLS session ticket lifetime hint: 64800 (seconds) TLS session ticket: 0000 - 21 3f a1 48 37 6f e4 cb-1e 1f 39 a4 a3 64 6e 10 !?.H7o....9..dn. 0010 - 03 30 66 da d4 40 d4 a9-ef e8 a4 fc 59 46 0b 5e .0f..@......YF.^ 0020 - d5 b2 1e 67 41 4e 79 f9-3f cf 08 fd 4a d7 46 cf ...gANy.?...J.F. 0030 - 16 8f c3 cf 30 45 14 e2-80 bd ee 3d 0f d4 5d e9 ....0E.....=..]. 0040 - 67 7c 22 5c e7 46 69 45-22 23 71 3e 09 b5 22 03 g|"\.FiE"#q>..". 0050 - 73 9e a2 9f 10 3a 72 fc-b3 c2 3c 2a 81 1d e6 a3 s....:r...<*.... 0060 - f3 19 6a 5e b3 e4 be 52-34 d3 ad 85 0a 11 4d 01 ..j^...R4.....M. 0070 - bf aa 82 91 a0 05 53 b2-f1 31 b4 47 49 d4 6c 8f ......S..1.GI.l. 0080 - 13 80 15 96 c7 7a cf 08-b7 91 42 ff 03 63 3d aa .....z....B..c=. 0090 - 22 24 58 e5 fd 9e 2e f7-be ae 8f d6 f2 fb 00 9f "$X............. 00a0 - 33 df 82 0c 4f a2 09 20-f0 f3 13 f6 f0 fc 75 3b 3...O.. ......u; 00b0 - 5d 37 50 a3 48 a9 2b 53-67 df a2 ae e0 54 1f bc ]7P.H.+Sg....T.. Start Time: 1542948064 Timeout : 7200 (sec) Verify return code: 20 (unable to get local issuer certificate) Extended master secret: yes Client-Random (32/32 bytes) 00000000 4F 87 34 3A 2A 2A 98 B6 | BA CD 0E 44 29 7F F0 84 [O.4:**.....D)...] 00000010 16 8D 01 9F 3B 45 7E 81 | 2B 91 49 27 53 F6 03 DC [....;E~.+.I'S...] Server-Random (32/32 bytes) 00000000 5B F7 84 E0 F1 E5 51 7D | 75 D0 BB 61 CA 10 90 23 [[.....Q}u..a...#] 00000010 7B 92 57 34 17 12 7D BE | 44 4F 57 4E 47 52 44 01 [{.W4..}.DOWNGRD.] Master-Key(Master-Secret) (48/48 bytes) 00000000 BD 47 7F 8C 20 D8 FF 8E | 6A 0E F1 96 B6 05 50 8E [.G.. ...j.....P.] 00000010 9A 02 A9 8B 3E 3D 88 2D | CE 23 7F 72 50 7F EC 47 [....>=.-.#.rP..G] 00000020 D9 8A CA E6 29 17 C7 B7 | 12 58 75 DD 7B E9 71 24 [....)....Xu.{.q$] Key-Block (label="key expansion", 56 bytes) 00000000 A0 F7 E5 0A D2 15 EF BD | B6 39 89 2A 09 08 BD 74 [.........9.*...t] 00000010 4F 50 D1 6C C2 A4 5A F6 | 26 86 94 67 CB 54 3F 8E [OP.l..Z.&..g.T?.] 00000020 39 22 D0 86 77 D1 7C FB | C8 6C 33 F5 D5 FA 39 92 [9"..w.|..l3...9.] 00000030 08 67 0F 1F B7 F4 80 AE [.g...... ] Dump crypto_info - client, for decrypt - version : 00000303H - cipher_type : 51 - iv (8 bytes) 00000000 00 00 00 00 00 00 00 00 [........ ] - key (16 bytes) 00000000 4F 50 D1 6C C2 A4 5A F6 | 26 86 94 67 CB 54 3F 8E [OP.l..Z.&..g.T?.] - salt (4 bytes) 00000000 77 D1 7C FB [w.|. ] - rec_seq (8 bytes) 00000000 00 00 00 00 00 00 00 01 [........ ] SOL_TCP/TCP_ULP(client, for decrypt) supported. (fd=7) Client-Random (32/32 bytes) 00000000 4F 87 34 3A 2A 2A 98 B6 | BA CD 0E 44 29 7F F0 84 [O.4:**.....D)...] 00000010 16 8D 01 9F 3B 45 7E 81 | 2B 91 49 27 53 F6 03 DC [....;E~.+.I'S...] Server-Random (32/32 bytes) 00000000 5B F7 84 E0 F1 E5 51 7D | 75 D0 BB 61 CA 10 90 23 [[.....Q}u..a...#] 00000010 7B 92 57 34 17 12 7D BE | 44 4F 57 4E 47 52 44 01 [{.W4..}.DOWNGRD.] Master-Key(Master-Secret) (48/48 bytes) 00000000 BD 47 7F 8C 20 D8 FF 8E | 6A 0E F1 96 B6 05 50 8E [.G.. ...j.....P.] 00000010 9A 02 A9 8B 3E 3D 88 2D | CE 23 7F 72 50 7F EC 47 [....>=.-.#.rP..G] 00000020 D9 8A CA E6 29 17 C7 B7 | 12 58 75 DD 7B E9 71 24 [....)....Xu.{.q$] Key-Block (label="key expansion", 56 bytes) 00000000 A0 F7 E5 0A D2 15 EF BD | B6 39 89 2A 09 08 BD 74 [.........9.*...t] 00000010 4F 50 D1 6C C2 A4 5A F6 | 26 86 94 67 CB 54 3F 8E [OP.l..Z.&..g.T?.] 00000020 39 22 D0 86 77 D1 7C FB | C8 6C 33 F5 D5 FA 39 92 [9"..w.|..l3...9.] 00000030 08 67 0F 1F B7 F4 80 AE [.g...... ] Dump crypto_info - client, for encrypt - version : 00000303H - cipher_type : 51 - iv (8 bytes) 00000000 4B 00 2F 71 4C FE B9 77 [K./qL..w ] - key (16 bytes) 00000000 A0 F7 E5 0A D2 15 EF BD | B6 39 89 2A 09 08 BD 74 [.........9.*...t] - salt (4 bytes) 00000000 39 22 D0 86 [9".. ] - rec_seq (8 bytes) 00000000 00 00 00 00 00 00 00 01 [........ ] SOL_TCP/TCP_ULP(client, for encrypt) supported. (fd=7) From client rx (fd=6) 0 + 81 bytes (with kTLS) 00000000 47 45 54 20 2F 20 48 54 | 54 50 2F 31 2E 31 0D 0A [GET / HTTP/1.1..] 00000010 48 6F 73 74 3A 20 64 65 | 76 2E 6D 69 6E 7A 6B 6E [Host: dev.minzkn] 00000020 2E 63 6F 6D 3A 38 30 0D | 0A 55 73 65 72 2D 41 67 [.com:80..User-Ag] 00000030 65 6E 74 3A 20 63 75 72 | 6C 2F 37 2E 35 38 2E 30 [ent: curl/7.58.0] 00000040 0D 0A 41 63 63 65 70 74 | 3A 20 2A 2F 2A 0D 0A 0D [..Accept: */*...] 00000050 0A [. ] Pseudo-Encrypt to server (fd=7, tls-payloaod-size=110, plaintext-size=81) *** [PSEUDO-EN] 00000000 17 03 03 00 69 4B 00 2F | 71 4C FE B9 77 32 8A 6F [....iK./qL..w2.o] [PSEUDO-EN] 00000010 BC D1 79 7E A4 DD 90 6F | F0 D1 5F 12 C2 51 6D D0 [..y~...o.._..Qm.] [PSEUDO-EN] 00000020 C9 93 01 EC EF 57 6B 0D | 79 37 7B E4 79 0F E0 6F [.....Wk.y7{.y..o] [PSEUDO-EN] 00000030 A1 E7 8C 53 06 CF 91 D5 | CA F2 0F E5 C7 88 72 F4 [...S..........r.] [PSEUDO-EN] 00000040 DB 69 16 39 00 82 94 5F | 30 FC 81 2D CB 3D 62 65 [.i.9..._0..-.=be] [PSEUDO-EN] 00000050 AA 53 AD 54 4E C9 01 92 | EA E6 92 32 33 FC B8 39 [.S.TN......23..9] [PSEUDO-EN] 00000060 8A F6 BB 17 98 FB 8F 65 | D4 4A 32 E9 94 EF [.......e.J2... ] To server tx (fd=7) 0 + 81 bytes (with kTLS) 00000000 47 45 54 20 2F 20 48 54 | 54 50 2F 31 2E 31 0D 0A [GET / HTTP/1.1..] 00000010 48 6F 73 74 3A 20 64 65 | 76 2E 6D 69 6E 7A 6B 6E [Host: dev.minzkn] 00000020 2E 63 6F 6D 3A 38 30 0D | 0A 55 73 65 72 2D 41 67 [.com:80..User-Ag] 00000030 65 6E 74 3A 20 63 75 72 | 6C 2F 37 2E 35 38 2E 30 [ent: curl/7.58.0] 00000040 0D 0A 41 63 63 65 70 74 | 3A 20 2A 2F 2A 0D 0A 0D [..Accept: */*...] 00000050 0A [. ] From server rx (fd=7) 0 + 350 bytes (with kTLS) 00000000 48 54 54 50 2F 31 2E 31 | 20 34 30 33 20 46 6F 72 [HTTP/1.1 403 For] 00000010 62 69 64 64 65 6E 0D 0A | 53 65 72 76 65 72 3A 20 [bidden..Server: ] 00000020 63 6C 6F 75 64 66 6C 61 | 72 65 0D 0A 44 61 74 65 [cloudflare..Date] 00000030 3A 20 46 72 69 2C 20 32 | 33 20 4E 6F 76 20 32 30 [: Fri, 23 Nov 20] 00000040 31 38 20 30 34 3A 34 31 | 3A 30 34 20 47 4D 54 0D [18 04:41:04 GMT.] 00000050 0A 43 6F 6E 74 65 6E 74 | 2D 54 79 70 65 3A 20 74 [.Content-Type: t] 00000060 65 78 74 2F 68 74 6D 6C | 0D 0A 43 6F 6E 74 65 6E [ext/html..Conten] 00000070 74 2D 4C 65 6E 67 74 68 | 3A 20 31 36 37 0D 0A 43 [t-Length: 167..C] 00000080 6F 6E 6E 65 63 74 69 6F | 6E 3A 20 6B 65 65 70 2D [onnection: keep-] 00000090 61 6C 69 76 65 0D 0A 43 | 46 2D 52 41 59 3A 20 34 [alive..CF-RAY: 4] 000000A0 37 65 30 66 36 31 64 35 | 61 37 32 61 32 32 64 2D [7e0f61d5a72a22d-] 000000B0 49 43 4E 0D 0A 0D 0A 3C | 68 74 6D 6C 3E 0D 0A 3C [ICN....<html>..<] 000000C0 68 65 61 64 3E 3C 74 69 | 74 6C 65 3E 34 30 33 20 [head><title>403 ] 000000D0 46 6F 72 62 69 64 64 65 | 6E 3C 2F 74 69 74 6C 65 [Forbidden</title] 000000E0 3E 3C 2F 68 65 61 64 3E | 0D 0A 3C 62 6F 64 79 20 [></head>..<body ] 000000F0 62 67 63 6F 6C 6F 72 3D | 22 77 68 69 74 65 22 3E [bgcolor="white">] 00000100 0D 0A 3C 63 65 6E 74 65 | 72 3E 3C 68 31 3E 34 30 [..<center><h1>40] 00000110 33 20 46 6F 72 62 69 64 | 64 65 6E 3C 2F 68 31 3E [3 Forbidden</h1>] 00000120 3C 2F 63 65 6E 74 65 72 | 3E 0D 0A 3C 68 72 3E 3C [</center>..<hr><] 00000130 63 65 6E 74 65 72 3E 63 | 6C 6F 75 64 66 6C 61 72 [center>cloudflar] 00000140 65 3C 2F 63 65 6E 74 65 | 72 3E 0D 0A 3C 2F 62 6F [e</center>..</bo] 00000150 64 79 3E 0D 0A 3C 2F 68 | 74 6D 6C 3E 0D 0A [dy>..</html>.. ] Pseudo-Encrypt to client (fd=6, tls-payloaod-size=379, plaintext-size=350) *** [PSEUDO-EN] 00000000 17 03 03 01 76 D1 A5 F4 | 96 F7 8B FA 4D C2 92 D0 [....v.......M...] [PSEUDO-EN] 00000010 B3 F2 BE 59 B0 54 F4 55 | 8E E1 A1 54 23 2C 15 AF [...Y.T.U...T#,..] [PSEUDO-EN] 00000020 BD BC 0A 3F 40 DD 83 D9 | DC B1 58 D8 4E 74 EB 4E [...?@.....X.Nt.N] [PSEUDO-EN] 00000030 23 AA CF 74 4C 4F 5B 95 | AD 31 1A 4C 00 83 3E 1B [#..tLO[..1.L..>.] [PSEUDO-EN] 00000040 32 9F A9 6F 89 22 52 EE | 90 4C 79 60 16 EB E3 AA [2..o."R..Ly`....] [PSEUDO-EN] 00000050 7E 44 58 8A E1 4B 95 30 | 8B DE FE 7C 77 BD E7 2C [~DX..K.0...|w..,] [PSEUDO-EN] 00000060 62 00 D8 A0 9E 12 47 40 | 76 56 7C 93 2E A3 C0 BA [b.....G@vV|.....] [PSEUDO-EN] 00000070 49 0F C6 1D CD 39 CE 79 | C9 FD C4 94 DC 67 1F 3B [I....9.y.....g.;] [PSEUDO-EN] 00000080 4F BD 81 3F 5D 8F 2D 5A | 9D A4 F1 99 FD 69 22 85 [O..?].-Z.....i".] [PSEUDO-EN] 00000090 0A 55 D7 9E 66 8B FD 32 | 7C 3F 1A 22 45 30 5B C4 [.U..f..2|?."E0[.] [PSEUDO-EN] 000000A0 AC BA 15 7E 0A 7B 25 51 | 1F 5A 84 4C 47 E1 34 5D [...~.{%Q.Z.LG.4]] [PSEUDO-EN] 000000B0 E6 96 1B FC F8 6E EB 8E | 36 C8 FA 2F 7F DD 32 91 [.....n..6../..2.] [PSEUDO-EN] 000000C0 E6 5E 1E 76 FE A3 A6 63 | 1F D4 00 D5 84 CB 98 AF [.^.v...c........] [PSEUDO-EN] 000000D0 34 69 62 9C 95 36 86 72 | 17 58 48 00 0C E8 54 64 [4ib..6.r.XH...Td] [PSEUDO-EN] 000000E0 11 2F 04 4F AD A4 19 24 | 48 AB 37 24 2B 05 3F A8 [./.O...$H.7$+.?.] [PSEUDO-EN] 000000F0 0A C5 8B 76 77 73 FC 04 | 71 A7 D9 17 DF 42 55 A1 [...vws..q....BU.] [PSEUDO-EN] 00000100 19 50 26 D4 0F F3 1B DF | 71 A7 84 08 BD E5 8A 03 [.P&.....q.......] [PSEUDO-EN] 00000110 B7 D3 1E BC 4B 9B 2B A2 | 71 ED C4 BE 65 95 90 5E [....K.+.q...e..^] [PSEUDO-EN] 00000120 31 A2 15 35 B1 F7 D5 E5 | 5A 0B 32 EE 3E DC C6 1A [1..5....Z.2.>...] [PSEUDO-EN] 00000130 EC 07 CF 6E FA A1 00 D1 | E9 F0 BA 52 DE 8A CD 17 [...n.......R....] [PSEUDO-EN] 00000140 26 52 00 5C 79 97 35 1F | 20 5E 92 5C 97 D4 CF EA [&R.\y.5. ^.\....] [PSEUDO-EN] 00000150 4E 26 04 DD 09 81 D6 CA | 9A 5A A6 86 4D 54 F7 AA [N&.......Z..MT..] [PSEUDO-EN] 00000160 DD EE 98 C5 D8 13 B6 77 | 73 F5 13 F4 50 4E C4 C6 [.......ws...PN..] [PSEUDO-EN] 00000170 4C EF 9D 96 10 24 E7 6A | B0 D3 8E [L....$.j... ] To client tx (fd=6) 0 + 350 bytes (with kTLS) 00000000 48 54 54 50 2F 31 2E 31 | 20 34 30 33 20 46 6F 72 [HTTP/1.1 403 For] 00000010 62 69 64 64 65 6E 0D 0A | 53 65 72 76 65 72 3A 20 [bidden..Server: ] 00000020 63 6C 6F 75 64 66 6C 61 | 72 65 0D 0A 44 61 74 65 [cloudflare..Date] 00000030 3A 20 46 72 69 2C 20 32 | 33 20 4E 6F 76 20 32 30 [: Fri, 23 Nov 20] 00000040 31 38 20 30 34 3A 34 31 | 3A 30 34 20 47 4D 54 0D [18 04:41:04 GMT.] 00000050 0A 43 6F 6E 74 65 6E 74 | 2D 54 79 70 65 3A 20 74 [.Content-Type: t] 00000060 65 78 74 2F 68 74 6D 6C | 0D 0A 43 6F 6E 74 65 6E [ext/html..Conten] 00000070 74 2D 4C 65 6E 67 74 68 | 3A 20 31 36 37 0D 0A 43 [t-Length: 167..C] 00000080 6F 6E 6E 65 63 74 69 6F | 6E 3A 20 6B 65 65 70 2D [onnection: keep-] 00000090 61 6C 69 76 65 0D 0A 43 | 46 2D 52 41 59 3A 20 34 [alive..CF-RAY: 4] 000000A0 37 65 30 66 36 31 64 35 | 61 37 32 61 32 32 64 2D [7e0f61d5a72a22d-] 000000B0 49 43 4E 0D 0A 0D 0A 3C | 68 74 6D 6C 3E 0D 0A 3C [ICN....<html>..<] 000000C0 68 65 61 64 3E 3C 74 69 | 74 6C 65 3E 34 30 33 20 [head><title>403 ] 000000D0 46 6F 72 62 69 64 64 65 | 6E 3C 2F 74 69 74 6C 65 [Forbidden</title] 000000E0 3E 3C 2F 68 65 61 64 3E | 0D 0A 3C 62 6F 64 79 20 [></head>..<body ] 000000F0 62 67 63 6F 6C 6F 72 3D | 22 77 68 69 74 65 22 3E [bgcolor="white">] 00000100 0D 0A 3C 63 65 6E 74 65 | 72 3E 3C 68 31 3E 34 30 [..<center><h1>40] 00000110 33 20 46 6F 72 62 69 64 | 64 65 6E 3C 2F 68 31 3E [3 Forbidden</h1>] 00000120 3C 2F 63 65 6E 74 65 72 | 3E 0D 0A 3C 68 72 3E 3C [</center>..<hr><] 00000130 63 65 6E 74 65 72 3E 63 | 6C 6F 75 64 66 6C 61 72 [center>cloudflar] 00000140 65 3C 2F 63 65 6E 74 65 | 72 3E 0D 0A 3C 2F 62 6F [e</center>..</bo] 00000150 64 79 3E 0D 0A 3C 2F 68 | 74 6D 6C 3E 0D 0A [dy>..</html>.. ]
1.6. 참고자료
- Diffie-Hellman Key Agreement Method (Diffie-Hellman 키 분배 방법)
- VPN(Virtual Private Network, 가상사설망)
- 인증서 만들기
- hwport_aes : AES 암호화/부호화 library (ECB, CFB8, OFB8)
- mzcrc : CRC 16/32/64 를 표준에 입각하여 구현한 library
- mzdes : DES/3DES 암호화/부호화 library (ECB)
- mzseed : SEED 암호화/부호화 library (ECB)
- mzmd5 : MD5 digest library (HASH)
- mzpwcrack : Linux password cracker 예제
- SSL 3.0 (RFC 6101)
- TLS 1.0 (RFC 2246)
- TLS 1.1 (RFC 4346)
- TLS 1.2 (RFC 5246)
- AES Galois Counter Mode (GCM) Cipher Suites for TLS
- Partion Decryption (첨부문서 "pismenny-tlscrypto-talk.pptx" 의 내용 인용)
- PKCS #10: Certification Request Syntax Specification Version 1.7
- Internet X.509 Public Key Infrastructure Certificate and Certificate Revocation List (CRL) Profile
- Playing with Kernel TLS in Python
- PLAYING WITH KERNEL TLS IN LINUX 4.13 AND GO
- Linux 4.13 Kernel Launches With Accelerated Security Feature
- LWN: TLS in the kernel
- Linux Kernel Documentation : tls.txt
- Linux Solution Overview – MITM Attacks and SSL/TLS
- Linux Programmer's Manual : CMSG
- KCM(The kernel connection multiplexer)
- HTTPS와 SSL 인증서
- The First Few Milliseconds of an HTTPS Connection
- Use SSLsplit to transparently sniff TLS/SSL connections – including non-HTTP(S) protocols
- Traffic Analysis of an SSL/TLS Session
- SSL Introduction with Sample Transaction and Packet Exchange
- An overview of the SSL or TLS handshake
- DPDK (DATA PLANE DEVELOPMENT KIT)
- MITM(man in the middle attack, 중간자 공격)
- The Illustrated TLS Connection
[TLS v1.3] 2. TLS v1.3 의 장점은 무엇일까? – 2) 보안성향상
- IPSec과 SSL
- mitmproxy is a free and open source interactive HTTPS proxy.
- Negotiating secure connections through a proxy server
- avast 의 Man in The Middle Attack을 통한 SSL/TLS 스캐닝 기능 중지하기
- 95% of HTTPS servers vulnerable to trivial MITM attacks
- Detection and Mitigation of HTTPS Man-in-the-Middles and Impersonators
- TLS nonce-nse
- EVP Symmetric Encryption and Decryption
- GCM-AEAD support for ubuntu system running linux kernel-3.10
- Kernel Crypto API Architecture
- Linux Core Crypto User Guide (OpenSSL 의 crypto accelation 에 대한 측정)
- T-Proxy의 splice syscall 사용예제 소스
- The design of lock_sock() in Linux kernel
- 작업 큐 (INIT_DELAYED_WORK, mod_delayed_work, cancel_delayed_work, cancel_delayed_work_sync) 정리
- Galois/Counter Mode (GCM) and GMAC with AES example source