mirror of
https://github.com/guanzhi/GmSSL.git
synced 2026-06-27 15:43:42 +08:00
Add SM4-FF1, update socket API
This commit is contained in:
@@ -123,6 +123,7 @@ option(ENABLE_SM4_CFB "Enable SM4 CFB mode" ON)
|
||||
option(ENABLE_SM4_CCM "Enable SM4 CCM mode" ON)
|
||||
option(ENABLE_SM4_XTS "Enable SM4 XTS mode" ON)
|
||||
option(ENABLE_SM4_CBC_MAC "Enable SM4-CBC-MAC" ON)
|
||||
option(ENABLE_SM4_FF1 "Enable SM4 FF1 format-preserving encryption" ON)
|
||||
|
||||
option(ENABLE_SM9 "Enable SM9" ON)
|
||||
option(ENABLE_CMS "Enable CMS" ON)
|
||||
@@ -463,6 +464,14 @@ if (ENABLE_SM4_XTS)
|
||||
list(APPEND tests sm4_xts)
|
||||
endif()
|
||||
|
||||
if (ENABLE_SM4_FF1)
|
||||
message(STATUS "ENABLE_SM4_FF1 is ON")
|
||||
add_definitions(-DENABLE_SM4_FF1)
|
||||
list(APPEND src src/ff1.c)
|
||||
list(APPEND tools tools/sm4_ff1.c)
|
||||
list(APPEND tests ff1)
|
||||
endif()
|
||||
|
||||
|
||||
if (ENABLE_SM9)
|
||||
message(STATUS "ENABLE_SM9 is ON")
|
||||
@@ -825,6 +834,7 @@ add_test(NAME tool_sm4 COMMAND ${CMAKE_COMMAND}
|
||||
-DENABLE_SM4_CCM=${ENABLE_SM4_CCM}
|
||||
-DENABLE_SM4_XTS=${ENABLE_SM4_XTS}
|
||||
-DENABLE_SM4_CBC_MAC=${ENABLE_SM4_CBC_MAC}
|
||||
-DENABLE_SM4_FF1=${ENABLE_SM4_FF1}
|
||||
-P "${CMAKE_SOURCE_DIR}/cmake/tool_sm4.cmake")
|
||||
if(ENABLE_ZUC)
|
||||
add_test(NAME tool_zuc COMMAND ${CMAKE_COMMAND} -P "${CMAKE_SOURCE_DIR}/cmake/tool_zuc.cmake")
|
||||
@@ -932,7 +942,7 @@ endif()
|
||||
#
|
||||
set(CPACK_PACKAGE_NAME "GmSSL")
|
||||
set(CPACK_PACKAGE_VENDOR "GmSSL develop team")
|
||||
set(CPACK_PACKAGE_VERSION "3.3.0-dev.1154")
|
||||
set(CPACK_PACKAGE_VERSION "3.3.0-dev.1155")
|
||||
set(CPACK_PACKAGE_DESCRIPTION_FILE ${PROJECT_SOURCE_DIR}/README.md)
|
||||
set(CPACK_NSIS_MODIFY_PATH ON)
|
||||
include(CPack)
|
||||
|
||||
@@ -4,6 +4,7 @@ set(SM4_KEY 0123456789abcdeffedcba9876543210)
|
||||
set(SM4_IV 00000000000000000000000000000000)
|
||||
set(SM4_HMAC_KEY 0123456789abcdeffedcba98765432100123456789abcdeffedcba98765432100123456789abcdeffedcba9876543210)
|
||||
set(SM4_XTS_KEY 0123456789abcdeffedcba987654321000112233445566778899aabbccddeeff)
|
||||
set(SM4_FF1_KEY 2b7e151628aed2a6abf7158809cf4f3c)
|
||||
set(SM4_TEXT "0123456789abcdef0123456789abcdef")
|
||||
|
||||
function(gmssl_symmetric_roundtrip name)
|
||||
@@ -48,6 +49,12 @@ if(ENABLE_SM4_XTS)
|
||||
-in tool_sm4_xts.cipher -out tool_sm4_xts.decrypt)
|
||||
gmssl_files_equal(tool_sm4_xts.plain tool_sm4_xts.decrypt)
|
||||
endif()
|
||||
if(ENABLE_SM4_FF1)
|
||||
gmssl_expect_stdout("2326982895499381"
|
||||
sm4_ff1 -encrypt -key ${SM4_FF1_KEY} -tweak 39383736353433323130 -digits 6226090102675688)
|
||||
gmssl_expect_stdout("6226090102675688"
|
||||
sm4_ff1 -decrypt -key ${SM4_FF1_KEY} -tweak 39383736353433323130 -digits 2326982895499381)
|
||||
endif()
|
||||
if(ENABLE_SM4_CBC_MAC)
|
||||
gmssl_expect_stdout("9054fccff72871fdad5202c821dbea05\n"
|
||||
sm4_cbc_mac -key ${SM4_KEY} -in_str abc)
|
||||
|
||||
41
include/gmssl/ff1.h
Normal file
41
include/gmssl/ff1.h
Normal file
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright 2014-2026 The GmSSL Project. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||||
* not use this file except in compliance with the License.
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*/
|
||||
|
||||
#ifndef GMSSL_FF1_H
|
||||
#define GMSSL_FF1_H
|
||||
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <gmssl/block_cipher.h>
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
#define FF1_MIN_DIGITS 8
|
||||
#define FF1_MAX_DIGITS 18
|
||||
#define FF1_MIN_TWEAK_SIZE 0
|
||||
#define FF1_MAX_TWEAK_SIZE 11
|
||||
#define FF1_NUM_ROUNDS 10
|
||||
|
||||
|
||||
int ff1_init(BLOCK_CIPHER_KEY *key, const BLOCK_CIPHER *cipher, const uint8_t *raw_key);
|
||||
int ff1_encrypt(const BLOCK_CIPHER_KEY *key, const char *in, size_t inlen,
|
||||
const uint8_t *tweak, size_t tweaklen, char *out);
|
||||
int ff1_decrypt(const BLOCK_CIPHER_KEY *key, const char *in, size_t inlen,
|
||||
const uint8_t *tweak, size_t tweaklen, char *out);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
@@ -75,6 +75,7 @@ int tls_socket_set_nonblocking(tls_socket_t sock, int nonblock);
|
||||
tls_socket_t tls_socket_invalid(void);
|
||||
int tls_socket_is_valid(tls_socket_t sock);
|
||||
int tls_socket_create(tls_socket_t *sock, int af, int type, int protocl);
|
||||
int tls_socket_get_addr(const char *host, int port, struct sockaddr_in *addr);
|
||||
int tls_socket_connect(tls_socket_t sock, const struct sockaddr_in *addr);
|
||||
int tls_socket_bind(tls_socket_t sock, const struct sockaddr_in *addr);
|
||||
int tls_socket_listen(tls_socket_t sock, int backlog);
|
||||
|
||||
@@ -18,7 +18,7 @@ extern "C" {
|
||||
|
||||
|
||||
#define GMSSL_VERSION_NUM 30300
|
||||
#define GMSSL_VERSION_STR "GmSSL 3.3.0-dev.1154"
|
||||
#define GMSSL_VERSION_STR "GmSSL 3.3.0-dev.1155"
|
||||
|
||||
int gmssl_version_num(void);
|
||||
const char *gmssl_version_str(void);
|
||||
|
||||
308
src/ff1.c
Normal file
308
src/ff1.c
Normal file
@@ -0,0 +1,308 @@
|
||||
/*
|
||||
* Copyright 2014-2026 The GmSSL Project. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||||
* not use this file except in compliance with the License.
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*/
|
||||
|
||||
#include <gmssl/ff1.h>
|
||||
#include <string.h>
|
||||
#include <gmssl/endian.h>
|
||||
#include <gmssl/error.h>
|
||||
|
||||
|
||||
static const uint32_t ff1_radix10_mod[] = {
|
||||
1,
|
||||
10,
|
||||
100,
|
||||
1000,
|
||||
10000,
|
||||
100000,
|
||||
1000000,
|
||||
10000000,
|
||||
100000000,
|
||||
1000000000,
|
||||
};
|
||||
|
||||
static const size_t ff1_radix10_b[] = {
|
||||
0, 1, 1, 2, 2, 3, 3, 3, 4, 4,
|
||||
};
|
||||
|
||||
int ff1_init(BLOCK_CIPHER_KEY *key, const BLOCK_CIPHER *cipher, const uint8_t *raw_key)
|
||||
{
|
||||
if (!key || !cipher || !raw_key) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (cipher->block_size != BLOCK_CIPHER_BLOCK_SIZE) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (block_cipher_set_encrypt_key(key, cipher, raw_key) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int ff1_digits_to_num(const char *digits, size_t ndigits, uint32_t *num)
|
||||
{
|
||||
uint32_t value = 0;
|
||||
size_t i;
|
||||
|
||||
if (!digits || !num || ndigits > FF1_MAX_DIGITS/2) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
for (i = 0; i < ndigits; i++) {
|
||||
if (digits[i] < '0' || digits[i] > '9') {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
value = value * 10 + (uint32_t)(digits[i] - '0');
|
||||
}
|
||||
*num = value;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int ff1_num_to_digits(uint32_t num, size_t ndigits, char *digits)
|
||||
{
|
||||
if (!digits || ndigits > FF1_MAX_DIGITS/2 || num >= ff1_radix10_mod[ndigits]) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
while (ndigits) {
|
||||
digits[--ndigits] = (char)('0' + num % 10);
|
||||
num /= 10;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int ff1_check_args(const BLOCK_CIPHER_KEY *key, const char *in, size_t inlen,
|
||||
const uint8_t *tweak, size_t tweaklen, char *out)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if (!key || !key->cipher || !in || !out || (!tweak && tweaklen)) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (key->cipher->block_size != BLOCK_CIPHER_BLOCK_SIZE) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (inlen < FF1_MIN_DIGITS || inlen > FF1_MAX_DIGITS) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (tweaklen < FF1_MIN_TWEAK_SIZE || tweaklen > FF1_MAX_TWEAK_SIZE) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
for (i = 0; i < inlen; i++) {
|
||||
if (in[i] < '0' || in[i] > '9') {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int ff1_init_pblock(const BLOCK_CIPHER_KEY *key, uint8_t pblock[16],
|
||||
size_t u, size_t n, size_t tweaklen)
|
||||
{
|
||||
static const uint8_t ff1_radix10_pblock[16] = {
|
||||
0x01, 0x02, 0x01, 0x00, 0x00, 0x0a, 0x0a, 0xff,
|
||||
0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff,
|
||||
};
|
||||
|
||||
memcpy(pblock, ff1_radix10_pblock, 16);
|
||||
pblock[7] = (uint8_t)u;
|
||||
PUTU32(pblock + 8, (uint32_t)n);
|
||||
PUTU32(pblock + 12, (uint32_t)tweaklen);
|
||||
|
||||
if (block_cipher_encrypt(key, pblock, pblock) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int ff1_round(const BLOCK_CIPHER_KEY *key, const uint8_t pblock[16],
|
||||
const uint8_t *tweak, size_t tweaklen, size_t bsize, int round, uint32_t num, uint64_t *y)
|
||||
{
|
||||
uint8_t qblock[32] = {0};
|
||||
uint8_t block[16];
|
||||
size_t padlen;
|
||||
size_t offset;
|
||||
size_t qlen;
|
||||
size_t i;
|
||||
|
||||
if (!key || !pblock || (!tweak && tweaklen) || !bsize || bsize > sizeof(uint32_t)
|
||||
|| !y || round < 0 || round > 0xff) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Keep a full zero padding block when tweak || round || NUM(B) is block-aligned. */
|
||||
padlen = 16 - (tweaklen + 1 + bsize) % 16;
|
||||
qlen = tweaklen + padlen + 1 + bsize;
|
||||
if (!qlen || qlen > sizeof(qblock) || qlen % 16) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (tweaklen) {
|
||||
memcpy(qblock, tweak, tweaklen);
|
||||
}
|
||||
offset = tweaklen + padlen;
|
||||
qblock[offset++] = (uint8_t)round;
|
||||
for (i = 0; i < bsize; i++) {
|
||||
qblock[offset + bsize - 1 - i] = (uint8_t)(num >> (8 * i));
|
||||
}
|
||||
|
||||
for (i = 0; i < sizeof(block); i++) {
|
||||
block[i] = pblock[i] ^ qblock[i];
|
||||
}
|
||||
if (block_cipher_encrypt(key, block, block) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
for (offset = 16; offset < qlen; offset += 16) {
|
||||
for (i = 0; i < sizeof(block); i++) {
|
||||
block[i] ^= qblock[offset + i];
|
||||
}
|
||||
if (block_cipher_encrypt(key, block, block) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
*y = GETU64(block);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ff1_encrypt(const BLOCK_CIPHER_KEY *key, const char *in, size_t inlen,
|
||||
const uint8_t *tweak, size_t tweaklen, char *out)
|
||||
{
|
||||
size_t u;
|
||||
size_t v;
|
||||
uint32_t a;
|
||||
uint32_t b;
|
||||
size_t alen;
|
||||
size_t blen;
|
||||
uint64_t y;
|
||||
uint32_t ymod;
|
||||
uint32_t c;
|
||||
uint8_t pblock[16];
|
||||
size_t bsize;
|
||||
int i;
|
||||
|
||||
if (ff1_check_args(key, in, inlen, tweak, tweaklen, out) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
u = inlen / 2;
|
||||
v = inlen - u;
|
||||
|
||||
if (ff1_digits_to_num(in, u, &a) != 1
|
||||
|| ff1_digits_to_num(in + u, v, &b) != 1
|
||||
|| ff1_init_pblock(key, pblock, u, inlen, tweaklen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
alen = u;
|
||||
blen = v;
|
||||
bsize = ff1_radix10_b[v];
|
||||
|
||||
for (i = 0; i < FF1_NUM_ROUNDS; i++) {
|
||||
size_t m = (i & 1) ? v : u;
|
||||
|
||||
if (ff1_round(key, pblock, tweak, tweaklen, bsize, i, b, &y) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
ymod = (uint32_t)(y % ff1_radix10_mod[m]);
|
||||
c = (a + ymod) % ff1_radix10_mod[m];
|
||||
a = b;
|
||||
alen = blen;
|
||||
b = c;
|
||||
blen = m;
|
||||
}
|
||||
|
||||
if (alen != u || blen != v) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (ff1_num_to_digits(a, alen, out) != 1
|
||||
|| ff1_num_to_digits(b, blen, out + alen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ff1_decrypt(const BLOCK_CIPHER_KEY *key, const char *in, size_t inlen,
|
||||
const uint8_t *tweak, size_t tweaklen, char *out)
|
||||
{
|
||||
size_t u;
|
||||
size_t v;
|
||||
uint32_t a;
|
||||
uint32_t b;
|
||||
size_t alen;
|
||||
size_t blen;
|
||||
uint64_t y;
|
||||
uint32_t ymod;
|
||||
uint32_t c;
|
||||
uint8_t pblock[16];
|
||||
size_t bsize;
|
||||
int i;
|
||||
|
||||
if (ff1_check_args(key, in, inlen, tweak, tweaklen, out) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
u = inlen / 2;
|
||||
v = inlen - u;
|
||||
|
||||
if (ff1_digits_to_num(in, u, &a) != 1
|
||||
|| ff1_digits_to_num(in + u, v, &b) != 1
|
||||
|| ff1_init_pblock(key, pblock, u, inlen, tweaklen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
alen = u;
|
||||
blen = v;
|
||||
bsize = ff1_radix10_b[v];
|
||||
|
||||
for (i = FF1_NUM_ROUNDS - 1; i >= 0; i--) {
|
||||
size_t m = (i & 1) ? v : u;
|
||||
|
||||
c = b;
|
||||
b = a;
|
||||
blen = alen;
|
||||
|
||||
if (ff1_round(key, pblock, tweak, tweaklen, bsize, i, b, &y) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
ymod = (uint32_t)(y % ff1_radix10_mod[m]);
|
||||
a = c;
|
||||
a = (a >= ymod) ? a - ymod : a + ff1_radix10_mod[m] - ymod;
|
||||
alen = m;
|
||||
}
|
||||
|
||||
if (alen != u || blen != v) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (ff1_num_to_digits(a, alen, out) != 1
|
||||
|| ff1_num_to_digits(b, blen, out + alen) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
12
src/http.c
12
src/http.c
@@ -120,7 +120,6 @@ int http_get(const char *uri, uint8_t *buf, size_t *contentlen, size_t buflen)
|
||||
char host[128];
|
||||
int port;
|
||||
char path[256];
|
||||
struct hostent *hp;
|
||||
struct sockaddr_in server;
|
||||
tls_socket_t sock = tls_socket_invalid();
|
||||
char get[sizeof(HTTP_GET_TEMPLATE) + sizeof(host) + sizeof(path)];
|
||||
@@ -141,13 +140,10 @@ int http_get(const char *uri, uint8_t *buf, size_t *contentlen, size_t buflen)
|
||||
}
|
||||
|
||||
// connect and send request
|
||||
if (!(hp = gethostbyname(host))) {
|
||||
if (tls_socket_get_addr(host, port, &server) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
server.sin_addr = *((struct in_addr *)hp->h_addr_list[0]);
|
||||
server.sin_family = AF_INET;
|
||||
server.sin_port = htons(port);
|
||||
|
||||
if (tls_socket_create(&sock, AF_INET, SOCK_STREAM, 0) != 1) {
|
||||
error_print();
|
||||
@@ -198,7 +194,6 @@ int http_post(const char *uri, const char *content_type,
|
||||
char host[128];
|
||||
int port;
|
||||
char path[256];
|
||||
struct hostent *hp;
|
||||
struct sockaddr_in server;
|
||||
tls_socket_t sock = tls_socket_invalid();
|
||||
char post[1024];
|
||||
@@ -223,13 +218,10 @@ int http_post(const char *uri, const char *content_type,
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!(hp = gethostbyname(host))) {
|
||||
if (tls_socket_get_addr(host, port, &server) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
server.sin_addr = *((struct in_addr *)hp->h_addr_list[0]);
|
||||
server.sin_family = AF_INET;
|
||||
server.sin_port = htons(port);
|
||||
|
||||
if (tls_socket_create(&sock, AF_INET, SOCK_STREAM, 0) != 1) {
|
||||
error_print();
|
||||
|
||||
@@ -120,7 +120,6 @@ int http_get(const char *uri, uint8_t *buf, size_t *contentlen, size_t buflen)
|
||||
char host[128];
|
||||
int port;
|
||||
char path[256];
|
||||
struct hostent *hp;
|
||||
struct sockaddr_in server;
|
||||
tls_socket_t sock = tls_socket_invalid();
|
||||
char get[sizeof(HTTP_GET_TEMPLATE) + sizeof(host) + sizeof(path)];
|
||||
@@ -148,13 +147,10 @@ int http_get(const char *uri, uint8_t *buf, size_t *contentlen, size_t buflen)
|
||||
socket_lib_inited = 1;
|
||||
|
||||
// connect and send request
|
||||
if (!(hp = gethostbyname(host))) {
|
||||
if (tls_socket_get_addr(host, port, &server) != 1) {
|
||||
error_print();
|
||||
goto end;
|
||||
}
|
||||
server.sin_addr = *((struct in_addr *)hp->h_addr_list[0]);
|
||||
server.sin_family = AF_INET;
|
||||
server.sin_port = htons(port);
|
||||
|
||||
if (tls_socket_create(&sock, AF_INET, SOCK_STREAM, 0) != 1) {
|
||||
error_print();
|
||||
@@ -207,7 +203,6 @@ int http_post(const char *uri, const char *content_type,
|
||||
char host[128];
|
||||
int port;
|
||||
char path[256];
|
||||
struct hostent *hp;
|
||||
struct sockaddr_in server;
|
||||
tls_socket_t sock = tls_socket_invalid();
|
||||
char post[1024];
|
||||
@@ -239,13 +234,10 @@ int http_post(const char *uri, const char *content_type,
|
||||
}
|
||||
socket_lib_inited = 1;
|
||||
|
||||
if (!(hp = gethostbyname(host))) {
|
||||
if (tls_socket_get_addr(host, port, &server) != 1) {
|
||||
error_print();
|
||||
goto end;
|
||||
}
|
||||
server.sin_addr = *((struct in_addr *)hp->h_addr_list[0]);
|
||||
server.sin_family = AF_INET;
|
||||
server.sin_port = htons(port);
|
||||
|
||||
if (tls_socket_create(&sock, AF_INET, SOCK_STREAM, 0) != 1) {
|
||||
error_print();
|
||||
|
||||
42
src/socket.c
42
src/socket.c
@@ -18,6 +18,7 @@
|
||||
|
||||
#ifdef WIN32
|
||||
#include <windows.h>
|
||||
#include <ws2tcpip.h>
|
||||
#endif
|
||||
|
||||
|
||||
@@ -29,6 +30,47 @@ static int tls_socket_should_print_error(int err, int is_read)
|
||||
&& type != TLS_SOCKET_ERR_INTERRUPTED;
|
||||
}
|
||||
|
||||
int tls_socket_get_addr(const char *host, int port, struct sockaddr_in *addr)
|
||||
{
|
||||
char service[16];
|
||||
struct addrinfo hints;
|
||||
struct addrinfo *res = NULL;
|
||||
int err;
|
||||
|
||||
if (!host || !addr || port <= 0 || port > 65535) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (snprintf(service, sizeof(service), "%d", port) <= 0) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = AF_INET;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
|
||||
if ((err = getaddrinfo(host, service, &hints, &res)) != 0) {
|
||||
#ifdef WIN32
|
||||
error_print_msg("getaddrinfo error: %d (%s)\n", err, gai_strerrorA(err));
|
||||
#else
|
||||
error_print_msg("getaddrinfo error: %d (%s)\n", err, gai_strerror(err));
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
if (!res || res->ai_addrlen < sizeof(struct sockaddr_in)) {
|
||||
error_print();
|
||||
if (res) {
|
||||
freeaddrinfo(res);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy(addr, res->ai_addr, sizeof(struct sockaddr_in));
|
||||
freeaddrinfo(res);
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
|
||||
int tls_socket_get_error(void)
|
||||
|
||||
273
tests/ff1test.c
Normal file
273
tests/ff1test.c
Normal file
@@ -0,0 +1,273 @@
|
||||
/*
|
||||
* Copyright 2014-2026 The GmSSL Project. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||||
* not use this file except in compliance with the License.
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <gmssl/ff1.h>
|
||||
#include <gmssl/error.h>
|
||||
|
||||
|
||||
typedef struct {
|
||||
const uint8_t key[16];
|
||||
const char *plaintext;
|
||||
const uint8_t *tweak;
|
||||
size_t tweaklen;
|
||||
const char *ciphertext;
|
||||
} FF1_TEST;
|
||||
|
||||
static const uint8_t ff1_sm4_tweak1[] = {
|
||||
0x39, 0x38, 0x37, 0x36, 0x35, 0x34, 0x33, 0x32,
|
||||
0x31, 0x30,
|
||||
};
|
||||
|
||||
static const uint8_t ff1_sm4_tweak2[] = {
|
||||
0x37, 0x38, 0x39, 0x36, 0x70, 0x71, 0x72, 0x73,
|
||||
0x74, 0x75, 0x76,
|
||||
};
|
||||
|
||||
static const FF1_TEST ff1_sm4_tests[] = {
|
||||
{
|
||||
{
|
||||
0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
|
||||
0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c,
|
||||
},
|
||||
"6226090102675688",
|
||||
ff1_sm4_tweak1,
|
||||
sizeof(ff1_sm4_tweak1),
|
||||
"2326982895499381",
|
||||
},
|
||||
{
|
||||
{
|
||||
0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
|
||||
0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c,
|
||||
},
|
||||
"110107197203192876",
|
||||
ff1_sm4_tweak2,
|
||||
sizeof(ff1_sm4_tweak2),
|
||||
"755842115213533405",
|
||||
},
|
||||
{
|
||||
{
|
||||
0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
|
||||
0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c,
|
||||
},
|
||||
"13687260594",
|
||||
NULL,
|
||||
0,
|
||||
"37914960556",
|
||||
},
|
||||
};
|
||||
|
||||
#ifdef ENABLE_AES
|
||||
static const uint8_t ff1_aes128_tweak1[] = {
|
||||
0x39, 0x38, 0x37, 0x36, 0x35, 0x34, 0x33, 0x32,
|
||||
0x31, 0x30,
|
||||
};
|
||||
|
||||
static const uint8_t ff1_aes128_tweak4[] = {
|
||||
0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37,
|
||||
};
|
||||
|
||||
static const FF1_TEST ff1_aes128_tests[] = {
|
||||
{
|
||||
{
|
||||
0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
|
||||
0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c,
|
||||
},
|
||||
"0123456789",
|
||||
ff1_aes128_tweak1,
|
||||
sizeof(ff1_aes128_tweak1),
|
||||
"6124200773",
|
||||
},
|
||||
{
|
||||
{
|
||||
0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
|
||||
0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c,
|
||||
},
|
||||
"0123456789",
|
||||
NULL,
|
||||
0,
|
||||
"2433477484",
|
||||
},
|
||||
{
|
||||
{
|
||||
0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
|
||||
0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c,
|
||||
},
|
||||
"999999999",
|
||||
ff1_aes128_tweak4,
|
||||
sizeof(ff1_aes128_tweak4),
|
||||
"658229573",
|
||||
},
|
||||
};
|
||||
#endif
|
||||
|
||||
static int test_ff1_sm4(void)
|
||||
{
|
||||
const char *plaintext = "99999999999999999";
|
||||
size_t plaintext_len = strlen(plaintext);
|
||||
const char sentinel = '#';
|
||||
const uint8_t key[16] = {0};
|
||||
const uint8_t tweak[8] = {
|
||||
0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
|
||||
};
|
||||
BLOCK_CIPHER_KEY block_key;
|
||||
char ciphertext[FF1_MAX_DIGITS + 1];
|
||||
char decrypted[FF1_MAX_DIGITS + 1];
|
||||
|
||||
if (ff1_init(&block_key, BLOCK_CIPHER_sm4(), key) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
ciphertext[plaintext_len] = sentinel;
|
||||
if (ff1_encrypt(&block_key, plaintext, plaintext_len,
|
||||
tweak, sizeof(tweak), ciphertext) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (ciphertext[plaintext_len] != sentinel) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
ciphertext[plaintext_len] = '\0';
|
||||
decrypted[plaintext_len] = sentinel;
|
||||
if (ff1_decrypt(&block_key, ciphertext, plaintext_len,
|
||||
tweak, sizeof(tweak), decrypted) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (decrypted[plaintext_len] != sentinel) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
decrypted[plaintext_len] = '\0';
|
||||
if (strcmp(plaintext, decrypted) != 0) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("ff1-sm4-encrypt(\"%s\") = \"%s\"\n", plaintext, ciphertext);
|
||||
printf("%s() ok\n", __FUNCTION__);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int test_ff1_sm4_vectors(void)
|
||||
{
|
||||
BLOCK_CIPHER_KEY block_key;
|
||||
char ciphertext[FF1_MAX_DIGITS + 1];
|
||||
char decrypted[FF1_MAX_DIGITS + 1];
|
||||
size_t i;
|
||||
int err = 0;
|
||||
|
||||
for (i = 0; i < sizeof(ff1_sm4_tests)/sizeof(ff1_sm4_tests[0]); i++) {
|
||||
const FF1_TEST *test = &ff1_sm4_tests[i];
|
||||
|
||||
if (ff1_init(&block_key, BLOCK_CIPHER_sm4(), test->key) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (ff1_encrypt(&block_key, test->plaintext, strlen(test->plaintext),
|
||||
test->tweak, test->tweaklen, ciphertext) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
ciphertext[strlen(test->plaintext)] = '\0';
|
||||
if (strcmp(ciphertext, test->ciphertext) != 0) {
|
||||
fprintf(stderr, "test %zu: got %s, expected %s\n",
|
||||
i + 1, ciphertext, test->ciphertext);
|
||||
error_print();
|
||||
err++;
|
||||
continue;
|
||||
}
|
||||
if (ff1_decrypt(&block_key, test->ciphertext, strlen(test->ciphertext),
|
||||
test->tweak, test->tweaklen, decrypted) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
decrypted[strlen(test->ciphertext)] = '\0';
|
||||
if (strcmp(decrypted, test->plaintext) != 0) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (err) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("%s() ok\n", __FUNCTION__);
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_AES
|
||||
static int test_ff1_aes128_vectors(void)
|
||||
{
|
||||
BLOCK_CIPHER_KEY block_key;
|
||||
char ciphertext[FF1_MAX_DIGITS + 1];
|
||||
char decrypted[FF1_MAX_DIGITS + 1];
|
||||
size_t i;
|
||||
int err = 0;
|
||||
|
||||
for (i = 0; i < sizeof(ff1_aes128_tests)/sizeof(ff1_aes128_tests[0]); i++) {
|
||||
const FF1_TEST *test = &ff1_aes128_tests[i];
|
||||
|
||||
if (ff1_init(&block_key, BLOCK_CIPHER_aes128(), test->key) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
if (ff1_encrypt(&block_key, test->plaintext, strlen(test->plaintext),
|
||||
test->tweak, test->tweaklen, ciphertext) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
ciphertext[strlen(test->plaintext)] = '\0';
|
||||
if (strcmp(ciphertext, test->ciphertext) != 0) {
|
||||
fprintf(stderr, "AES-128 test %zu: got %s, expected %s\n",
|
||||
i + 1, ciphertext, test->ciphertext);
|
||||
error_print();
|
||||
err++;
|
||||
continue;
|
||||
}
|
||||
if (ff1_decrypt(&block_key, test->ciphertext, strlen(test->ciphertext),
|
||||
test->tweak, test->tweaklen, decrypted) != 1) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
decrypted[strlen(test->ciphertext)] = '\0';
|
||||
if (strcmp(decrypted, test->plaintext) != 0) {
|
||||
error_print();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (err) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("%s() ok\n", __FUNCTION__);
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
if (test_ff1_sm4() != 1) {
|
||||
err++;
|
||||
}
|
||||
if (test_ff1_sm4_vectors() != 1) {
|
||||
err++;
|
||||
}
|
||||
#ifdef ENABLE_AES
|
||||
if (test_ff1_aes128_vectors() != 1) {
|
||||
err++;
|
||||
}
|
||||
#endif
|
||||
|
||||
return err;
|
||||
}
|
||||
@@ -56,6 +56,9 @@ extern int sm4_gcm_main(int argc, char **argv);
|
||||
#ifdef ENABLE_SM4_XTS
|
||||
extern int sm4_xts_main(int argc, char **argv);
|
||||
#endif
|
||||
#ifdef ENABLE_SM4_FF1
|
||||
extern int sm4_ff1_main(int argc, char **argv);
|
||||
#endif
|
||||
extern int sm4_cbc_sm3_hmac_main(int argc, char **argv);
|
||||
extern int sm4_ctr_sm3_hmac_main(int argc, char **argv);
|
||||
#ifdef ENABLE_SM4_CBC_MAC
|
||||
@@ -160,6 +163,9 @@ static const char *options =
|
||||
#ifdef ENABLE_SM4_XTS
|
||||
" sm4_xts Encrypt or decrypt with SM4 XTS\n"
|
||||
#endif
|
||||
#ifdef ENABLE_SM4_FF1
|
||||
" sm4_ff1 Encrypt or decrypt digits with SM4 FF1\n"
|
||||
#endif
|
||||
#ifdef ENABLE_SM4_ECB
|
||||
" sm4_ecb Encrypt or decrypt with SM4 ECB\n"
|
||||
#endif
|
||||
@@ -355,6 +361,10 @@ int main(int argc, char **argv)
|
||||
#if ENABLE_SM4_XTS
|
||||
} else if (!strcmp(*argv, "sm4_xts")) {
|
||||
return sm4_xts_main(argc, argv);
|
||||
#endif
|
||||
#if ENABLE_SM4_FF1
|
||||
} else if (!strcmp(*argv, "sm4_ff1")) {
|
||||
return sm4_ff1_main(argc, argv);
|
||||
#endif
|
||||
} else if (!strcmp(*argv, "sm4_cbc_sm3_hmac")) {
|
||||
return sm4_cbc_sm3_hmac_main(argc, argv);
|
||||
|
||||
356
tools/sm4_ff1.c
Normal file
356
tools/sm4_ff1.c
Normal file
@@ -0,0 +1,356 @@
|
||||
/*
|
||||
* Copyright 2014-2026 The GmSSL Project. All Rights Reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||||
* not use this file except in compliance with the License.
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <gmssl/ff1.h>
|
||||
#include <gmssl/hex.h>
|
||||
#include <gmssl/mem.h>
|
||||
#include <gmssl/error.h>
|
||||
|
||||
|
||||
#define SM4_FF1_MAX_TWEAK_SIZE FF1_MAX_TWEAK_SIZE
|
||||
#define ID_CARD_DIGITS 18
|
||||
#define ID_CARD_BODY_DIGITS 17
|
||||
|
||||
|
||||
static const char *usage =
|
||||
"{-encrypt|-decrypt} -key hex [-tweak hex] [-idcard|-bankcard] [-digits digits]";
|
||||
|
||||
static const char *options =
|
||||
"\n"
|
||||
"Options\n"
|
||||
"\n"
|
||||
" -encrypt Encrypt\n"
|
||||
" -decrypt Decrypt\n"
|
||||
" -key hex SM4 key in HEX format\n"
|
||||
" -tweak hex FF1 tweak in HEX format\n"
|
||||
" -digits digits Input digits, default from stdin\n"
|
||||
" -idcard Input is a Chinese resident identity card number\n"
|
||||
" -bankcard Input is a bank card number with Luhn check digit\n"
|
||||
"\n";
|
||||
|
||||
static uint8_t *read_content(FILE *infp, size_t *outlen, const char *prog)
|
||||
{
|
||||
const size_t maxlen = 4096;
|
||||
uint8_t *buf = NULL;
|
||||
size_t len;
|
||||
|
||||
if (!(buf = malloc(maxlen + 1))) {
|
||||
fprintf(stderr, "gmssl %s: malloc failure\n", prog);
|
||||
return NULL;
|
||||
}
|
||||
len = fread(buf, 1, maxlen, infp);
|
||||
if (ferror(infp)) {
|
||||
fprintf(stderr, "gmssl %s: read failure : %s\n", prog, strerror(errno));
|
||||
free(buf);
|
||||
return NULL;
|
||||
}
|
||||
if (!feof(infp)) {
|
||||
fprintf(stderr, "gmssl %s: input too long\n", prog);
|
||||
free(buf);
|
||||
return NULL;
|
||||
}
|
||||
while (len && (buf[len - 1] == '\n' || buf[len - 1] == '\r')) {
|
||||
len--;
|
||||
}
|
||||
buf[len] = 0;
|
||||
*outlen = len;
|
||||
return buf;
|
||||
}
|
||||
|
||||
static int is_digits(const char *s, size_t len)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if (!s) {
|
||||
return 0;
|
||||
}
|
||||
for (i = 0; i < len; i++) {
|
||||
if (s[i] < '0' || s[i] > '9') {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int idcard_check_digit(const char body[ID_CARD_BODY_DIGITS])
|
||||
{
|
||||
static const int weights[ID_CARD_BODY_DIGITS] = {
|
||||
7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2,
|
||||
};
|
||||
static const char check_digits[] = "10X98765432";
|
||||
int sum = 0;
|
||||
size_t i;
|
||||
|
||||
if (!is_digits(body, ID_CARD_BODY_DIGITS)) {
|
||||
return -1;
|
||||
}
|
||||
for (i = 0; i < ID_CARD_BODY_DIGITS; i++) {
|
||||
sum += (body[i] - '0') * weights[i];
|
||||
}
|
||||
return check_digits[sum % 11];
|
||||
}
|
||||
|
||||
static int idcard_check(const char *s, size_t len)
|
||||
{
|
||||
int ch;
|
||||
char last;
|
||||
|
||||
if (!s || len != ID_CARD_DIGITS) {
|
||||
return -1;
|
||||
}
|
||||
ch = idcard_check_digit(s);
|
||||
if (ch < 0) {
|
||||
return -1;
|
||||
}
|
||||
last = s[ID_CARD_DIGITS - 1];
|
||||
if (last == 'x') {
|
||||
last = 'X';
|
||||
}
|
||||
return last == ch ? 1 : -1;
|
||||
}
|
||||
|
||||
static int luhn_check_digit(const char *body, size_t len)
|
||||
{
|
||||
int sum = 0;
|
||||
int double_digit = 1;
|
||||
|
||||
if (!is_digits(body, len)) {
|
||||
return -1;
|
||||
}
|
||||
while (len) {
|
||||
int digit = body[--len] - '0';
|
||||
if (double_digit) {
|
||||
digit *= 2;
|
||||
if (digit > 9) {
|
||||
digit -= 9;
|
||||
}
|
||||
}
|
||||
sum += digit;
|
||||
double_digit = !double_digit;
|
||||
}
|
||||
return '0' + (10 - sum % 10) % 10;
|
||||
}
|
||||
|
||||
static int bankcard_check(const char *s, size_t len)
|
||||
{
|
||||
int ch;
|
||||
|
||||
if (!s || len < FF1_MIN_DIGITS + 1 || len > FF1_MAX_DIGITS + 1 || !is_digits(s, len)) {
|
||||
return -1;
|
||||
}
|
||||
ch = luhn_check_digit(s, len - 1);
|
||||
if (ch < 0) {
|
||||
return -1;
|
||||
}
|
||||
return s[len - 1] == ch ? 1 : -1;
|
||||
}
|
||||
|
||||
int sm4_ff1_main(int argc, char **argv)
|
||||
{
|
||||
int ret = 1;
|
||||
char *prog = argv[0];
|
||||
int enc = -1;
|
||||
int idcard = 0;
|
||||
int bankcard = 0;
|
||||
char *keyhex = NULL;
|
||||
char *tweakhex = NULL;
|
||||
char *digits = NULL;
|
||||
uint8_t key[16];
|
||||
uint8_t tweak[SM4_FF1_MAX_TWEAK_SIZE];
|
||||
size_t keylen = 0;
|
||||
size_t tweaklen = 0;
|
||||
uint8_t *inbuf = NULL;
|
||||
int inbuf_alloc = 0;
|
||||
size_t inlen;
|
||||
char outbuf[FF1_MAX_DIGITS + 2];
|
||||
size_t bodylen;
|
||||
BLOCK_CIPHER_KEY block_key;
|
||||
|
||||
argc--;
|
||||
argv++;
|
||||
|
||||
if (argc < 1) {
|
||||
fprintf(stderr, "usage: gmssl %s %s\n", prog, usage);
|
||||
return 1;
|
||||
}
|
||||
|
||||
while (argc > 0) {
|
||||
if (!strcmp(*argv, "-help")) {
|
||||
printf("usage: gmssl %s %s\n", prog, usage);
|
||||
printf("%s\n", options);
|
||||
ret = 0;
|
||||
goto end;
|
||||
} else if (!strcmp(*argv, "-encrypt")) {
|
||||
if (enc == 0) {
|
||||
fprintf(stderr, "gmssl %s: `-encrypt` and `-decrypt` should not be used together\n", prog);
|
||||
goto end;
|
||||
}
|
||||
enc = 1;
|
||||
} else if (!strcmp(*argv, "-decrypt")) {
|
||||
if (enc == 1) {
|
||||
fprintf(stderr, "gmssl %s: `-encrypt` and `-decrypt` should not be used together\n", prog);
|
||||
goto end;
|
||||
}
|
||||
enc = 0;
|
||||
} else if (!strcmp(*argv, "-key")) {
|
||||
if (--argc < 1) goto bad;
|
||||
keyhex = *(++argv);
|
||||
if (strlen(keyhex) != sizeof(key) * 2) {
|
||||
fprintf(stderr, "gmssl %s: invalid key length\n", prog);
|
||||
goto end;
|
||||
}
|
||||
if (hex_to_bytes(keyhex, strlen(keyhex), key, &keylen) != 1 || keylen != sizeof(key)) {
|
||||
fprintf(stderr, "gmssl %s: invalid key hex digits\n", prog);
|
||||
goto end;
|
||||
}
|
||||
} else if (!strcmp(*argv, "-tweak")) {
|
||||
if (--argc < 1) goto bad;
|
||||
tweakhex = *(++argv);
|
||||
if (strlen(tweakhex) > sizeof(tweak) * 2) {
|
||||
fprintf(stderr, "gmssl %s: invalid tweak length\n", prog);
|
||||
goto end;
|
||||
}
|
||||
if (!strlen(tweakhex)) {
|
||||
tweaklen = 0;
|
||||
} else if (hex_to_bytes(tweakhex, strlen(tweakhex), tweak, &tweaklen) != 1) {
|
||||
fprintf(stderr, "gmssl %s: invalid tweak hex digits\n", prog);
|
||||
goto end;
|
||||
}
|
||||
} else if (!strcmp(*argv, "-digits")) {
|
||||
if (--argc < 1) goto bad;
|
||||
if (digits) {
|
||||
fprintf(stderr, "gmssl %s: option `-digits` should be set only once\n", prog);
|
||||
goto end;
|
||||
}
|
||||
digits = *(++argv);
|
||||
} else if (!strcmp(*argv, "-idcard")) {
|
||||
if (bankcard) {
|
||||
fprintf(stderr, "gmssl %s: `-idcard` and `-bankcard` should not be used together\n", prog);
|
||||
goto end;
|
||||
}
|
||||
idcard = 1;
|
||||
} else if (!strcmp(*argv, "-bankcard")) {
|
||||
if (idcard) {
|
||||
fprintf(stderr, "gmssl %s: `-idcard` and `-bankcard` should not be used together\n", prog);
|
||||
goto end;
|
||||
}
|
||||
bankcard = 1;
|
||||
} else {
|
||||
fprintf(stderr, "gmssl %s: illegal option `%s`\n", prog, *argv);
|
||||
goto end;
|
||||
bad:
|
||||
fprintf(stderr, "gmssl %s: `%s` option value missing\n", prog, *argv);
|
||||
goto end;
|
||||
}
|
||||
|
||||
argc--;
|
||||
argv++;
|
||||
}
|
||||
|
||||
if (enc < 0) {
|
||||
fprintf(stderr, "gmssl %s: option -encrypt or -decrypt should be set\n", prog);
|
||||
goto end;
|
||||
}
|
||||
if (!keyhex) {
|
||||
fprintf(stderr, "gmssl %s: option `-key` missing\n", prog);
|
||||
goto end;
|
||||
}
|
||||
if (tweakhex && tweaklen > FF1_MAX_TWEAK_SIZE) {
|
||||
fprintf(stderr, "gmssl %s: invalid tweak length\n", prog);
|
||||
goto end;
|
||||
}
|
||||
if (digits) {
|
||||
inbuf = (uint8_t *)digits;
|
||||
inlen = strlen(digits);
|
||||
} else {
|
||||
if (!(inbuf = read_content(stdin, &inlen, prog))) {
|
||||
goto end;
|
||||
}
|
||||
inbuf_alloc = 1;
|
||||
}
|
||||
if (!inlen) {
|
||||
fprintf(stderr, "gmssl %s: empty input\n", prog);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (idcard) {
|
||||
if (idcard_check((char *)inbuf, inlen) != 1) {
|
||||
fprintf(stderr, "gmssl %s: invalid identity card number\n", prog);
|
||||
goto end;
|
||||
}
|
||||
bodylen = ID_CARD_BODY_DIGITS;
|
||||
} else if (bankcard) {
|
||||
if (bankcard_check((char *)inbuf, inlen) != 1) {
|
||||
fprintf(stderr, "gmssl %s: invalid bank card number\n", prog);
|
||||
goto end;
|
||||
}
|
||||
bodylen = inlen - 1;
|
||||
} else {
|
||||
if (inlen < FF1_MIN_DIGITS || inlen > FF1_MAX_DIGITS || !is_digits((char *)inbuf, inlen)) {
|
||||
fprintf(stderr, "gmssl %s: invalid input digits\n", prog);
|
||||
goto end;
|
||||
}
|
||||
bodylen = inlen;
|
||||
}
|
||||
|
||||
if (ff1_init(&block_key, BLOCK_CIPHER_sm4(), key) != 1) {
|
||||
error_print();
|
||||
goto end;
|
||||
}
|
||||
if (enc) {
|
||||
if (ff1_encrypt(&block_key, (char *)inbuf, bodylen, tweak, tweaklen, outbuf) != 1) {
|
||||
error_print();
|
||||
goto end;
|
||||
}
|
||||
} else {
|
||||
if (ff1_decrypt(&block_key, (char *)inbuf, bodylen, tweak, tweaklen, outbuf) != 1) {
|
||||
error_print();
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
if (idcard) {
|
||||
int ch = idcard_check_digit(outbuf);
|
||||
if (ch < 0) {
|
||||
error_print();
|
||||
goto end;
|
||||
}
|
||||
outbuf[bodylen] = (char)ch;
|
||||
outbuf[bodylen + 1] = '\0';
|
||||
bodylen++;
|
||||
} else if (bankcard) {
|
||||
int ch = luhn_check_digit(outbuf, bodylen);
|
||||
if (ch < 0) {
|
||||
error_print();
|
||||
goto end;
|
||||
}
|
||||
outbuf[bodylen] = (char)ch;
|
||||
outbuf[bodylen + 1] = '\0';
|
||||
bodylen++;
|
||||
}
|
||||
|
||||
if (fwrite(outbuf, 1, bodylen, stdout) != bodylen) {
|
||||
fprintf(stderr, "gmssl %s: output failure : %s\n", prog, strerror(errno));
|
||||
goto end;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
|
||||
end:
|
||||
if (inbuf_alloc) free(inbuf);
|
||||
gmssl_secure_clear(key, sizeof(key));
|
||||
gmssl_secure_clear(tweak, sizeof(tweak));
|
||||
gmssl_secure_clear(&block_key, sizeof(block_key));
|
||||
return ret;
|
||||
}
|
||||
@@ -228,7 +228,6 @@ int tlcp_client_main(int argc, char *argv[])
|
||||
char *infile = NULL;
|
||||
char *certoutfile = NULL;
|
||||
int verbose = 0;
|
||||
struct hostent *hp;
|
||||
struct sockaddr_in server;
|
||||
tls_socket_t sock = tls_socket_invalid();
|
||||
TLS_CTX ctx;
|
||||
@@ -479,15 +478,11 @@ bad:
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!(hp = gethostbyname(host))) {
|
||||
if (tls_socket_get_addr(host, port, &server) != 1) {
|
||||
fprintf(stderr, "%s: failed to parse host name '%s'\n", prog, host);
|
||||
goto end;
|
||||
}
|
||||
|
||||
server.sin_addr = *((struct in_addr *)hp->h_addr_list[0]);
|
||||
server.sin_family = AF_INET;
|
||||
server.sin_port = htons(port);
|
||||
|
||||
if (tls_socket_connect(sock, &server) != 1) {
|
||||
fprintf(stderr, "%s: failed to connect socket\n", prog);
|
||||
goto end;
|
||||
|
||||
@@ -220,7 +220,6 @@ int tls12_client_main(int argc, char *argv[])
|
||||
int verbose = 0;
|
||||
TLS_CTX ctx;
|
||||
TLS_CONNECT conn;
|
||||
struct hostent *hp;
|
||||
struct sockaddr_in server;
|
||||
tls_socket_t sock = tls_socket_invalid();
|
||||
char buf[1024] = {0};
|
||||
@@ -469,15 +468,11 @@ bad:
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!(hp = gethostbyname(host))) {
|
||||
if (tls_socket_get_addr(host, port, &server) != 1) {
|
||||
fprintf(stderr, "%s: failed to parse host name '%s'\n", prog, host);
|
||||
goto end;
|
||||
}
|
||||
|
||||
server.sin_addr = *((struct in_addr *)hp->h_addr_list[0]);
|
||||
server.sin_family = AF_INET;
|
||||
server.sin_port = htons(port);
|
||||
|
||||
if (tls_socket_connect(sock, &server) != 1) {
|
||||
fprintf(stderr, "%s: socket connect error\n", prog);
|
||||
goto end;
|
||||
|
||||
@@ -217,7 +217,6 @@ int tls13_client_main(int argc, char *argv[])
|
||||
TLS_CTX ctx;
|
||||
TLS_CONNECT conn;
|
||||
|
||||
struct hostent *hp;
|
||||
struct sockaddr_in server;
|
||||
tls_socket_t sock = tls_socket_invalid();
|
||||
char buf[1024] = {0};
|
||||
@@ -782,17 +781,10 @@ bad:
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!(hp = gethostbyname(host))) {
|
||||
#ifdef WIN32
|
||||
fprintf(stderr, "%s: parse -host value error: %d\n", prog, WSAGetLastError());
|
||||
#else
|
||||
fprintf(stderr, "%s: parse -host value error: %s\n", prog, hstrerror(h_errno));
|
||||
#endif
|
||||
if (tls_socket_get_addr(host, port, &server) != 1) {
|
||||
fprintf(stderr, "%s: parse -host value error\n", prog);
|
||||
goto end;
|
||||
}
|
||||
server.sin_addr = *((struct in_addr *)hp->h_addr_list[0]);
|
||||
server.sin_family = AF_INET;
|
||||
server.sin_port = htons(port);
|
||||
|
||||
if (tls_socket_create(&sock, AF_INET, SOCK_STREAM, 0) != 1) {
|
||||
fprintf(stderr, "%s: socket create error\n", prog);
|
||||
|
||||
Reference in New Issue
Block a user