diff --git a/Configure b/Configure index 348122db..d3041856 100755 --- a/Configure +++ b/Configure @@ -311,7 +311,7 @@ $config{sdirs} = [ "buffer", "bio", "stack", "lhash", "rand", "err", "evp", "asn1", "pem", "x509", "x509v3", "conf", "txt_db", "pkcs7", "pkcs12", "comp", "ocsp", "ui", "cms", "ts", "srp", "cmac", "ct", "async", "kdf", - "sm3" + "sm3", "sms4" ]; # Known TLS and DTLS protocols diff --git a/apps/progs.h b/apps/progs.h index 82b250c7..65e03fa0 100644 --- a/apps/progs.h +++ b/apps/progs.h @@ -236,6 +236,10 @@ static FUNCTION functions[] = { #ifndef OPENSSL_NO_BLAKE2 { FT_md, "blake2s256", dgst_main}, #endif + { FT_cipher, "sms4-cbc", enc_main, enc_options }, + { FT_cipher, "sms4-ecb", enc_main, enc_options }, + { FT_cipher, "sms4-ofb", enc_main, enc_options }, + { FT_cipher, "sms4-cfb", enc_main, enc_options }, { FT_cipher, "aes-128-cbc", enc_main, enc_options }, { FT_cipher, "aes-128-ecb", enc_main, enc_options }, { FT_cipher, "aes-192-cbc", enc_main, enc_options }, diff --git a/apps/progs.pl b/apps/progs.pl index ec3c1232..2bcb98f4 100644 --- a/apps/progs.pl +++ b/apps/progs.pl @@ -118,6 +118,7 @@ my %cipher_disabler = ( cast5 => "cast", ); foreach my $cmd ( + "sms4-cbc", "sms4-ecb", "sms4-ofb", "sms4-cfb", "aes-128-cbc", "aes-128-ecb", "aes-192-cbc", "aes-192-ecb", "aes-256-cbc", "aes-256-ecb", diff --git a/crypto/evp/build.info b/crypto/evp/build.info index e443d234..67d10492 100644 --- a/crypto/evp/build.info +++ b/crypto/evp/build.info @@ -13,7 +13,8 @@ SOURCE[../../libcrypto]=\ e_old.c pmeth_lib.c pmeth_fn.c pmeth_gn.c m_sigver.c \ e_aes_cbc_hmac_sha1.c e_aes_cbc_hmac_sha256.c e_rc4_hmac_md5.c \ e_chacha20_poly1305.c cmeth_lib.c \ - m_sm3.c + m_sm3.c \ + e_sms4.c e_sms4_ccm.c e_sms4_gcm.c e_sms4_ocb.c e_sms4_wrap.c e_sms4_xts.c INCLUDE[e_aes.o]=.. ../modes INCLUDE[e_aes_cbc_hmac_sha1.o]=../modes diff --git a/crypto/evp/c_allc.c b/crypto/evp/c_allc.c index 6ed31edb..ffef9c0c 100644 --- a/crypto/evp/c_allc.c +++ b/crypto/evp/c_allc.c @@ -216,5 +216,26 @@ void openssl_add_all_ciphers_int(void) # ifndef OPENSSL_NO_POLY1305 EVP_add_cipher(EVP_chacha20_poly1305()); # endif + +#ifndef OPENSSL_NO_SMS4 + EVP_add_cipher(EVP_sms4_ecb()); + EVP_add_cipher(EVP_sms4_cbc()); + EVP_add_cipher(EVP_sms4_cfb()); + EVP_add_cipher(EVP_sms4_cfb1()); + EVP_add_cipher(EVP_sms4_cfb8()); + EVP_add_cipher(EVP_sms4_ofb()); + EVP_add_cipher(EVP_sms4_ctr()); + EVP_add_cipher(EVP_sms4_ccm()); + EVP_add_cipher(EVP_sms4_gcm()); +# ifndef OPENSSL_NO_OCB + EVP_add_cipher(EVP_sms4_ocb()); +# endif + EVP_add_cipher(EVP_sms4_xts()); + EVP_add_cipher(EVP_sms4_wrap()); + EVP_add_cipher(EVP_sms4_wrap_pad()); + EVP_add_cipher_alias(SN_sms4_cbc,"SMS4"); + EVP_add_cipher_alias(SN_sms4_cbc,"sms4"); +#endif + #endif } diff --git a/crypto/evp/e_sms4.c b/crypto/evp/e_sms4.c new file mode 100644 index 00000000..ee06b353 --- /dev/null +++ b/crypto/evp/e_sms4.c @@ -0,0 +1,200 @@ +/* ==================================================================== + * Copyright (c) 2014 - 2017 The GmSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the GmSSL Project. + * (http://gmssl.org/)" + * + * 4. The name "GmSSL Project" must not be used to endorse or promote + * products derived from this software without prior written + * permission. For written permission, please contact + * guanzhi1980@gmail.com. + * + * 5. Products derived from this software may not be called "GmSSL" + * nor may "GmSSL" appear in their names without prior written + * permission of the GmSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the GmSSL Project + * (http://gmssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE GmSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE GmSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ + /* + * Copyright 2001-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include + +#include +#include +#include +#include "evp_locl.h" +# include "internal/evp_int.h" +#include "../modes/modes_lcl.h" + +#ifndef OPENSSL_NO_SMS4 + +# include + +typedef struct { + sms4_key_t ks; +} EVP_SMS4_KEY; + +static int sms4_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc) +{ + if (!enc) { + if (EVP_CIPHER_CTX_mode(ctx) == EVP_CIPH_OFB_MODE) + enc = 1; + else if (EVP_CIPHER_CTX_mode(ctx) == EVP_CIPH_CFB_MODE) + enc = 1; //encrypt key == decrypt key + } + + if (enc) + sms4_set_encrypt_key(ctx->cipher_data, key); + else sms4_set_decrypt_key(ctx->cipher_data, key); + + return 1; +} + +IMPLEMENT_BLOCK_CIPHER(sms4, ks, sms4, EVP_SMS4_KEY, NID_sms4, + SMS4_BLOCK_SIZE, SMS4_KEY_LENGTH, SMS4_IV_LENGTH, 128, 0, + sms4_init_key, NULL, NULL, NULL, NULL) + +# define MAXBITCHUNK ((size_t)1<<(sizeof(size_t)*8-4)) + +static int sms4_cfb1_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t len) +{ + EVP_SMS4_KEY *sms4_key = (EVP_SMS4_KEY *)ctx->cipher_data; + + if (ctx->flags & EVP_CIPH_FLAG_LENGTH_BITS) { + CRYPTO_cfb128_1_encrypt(in, out, len, &sms4_key->ks, + ctx->iv, &ctx->num, ctx->encrypt, (block128_f)sms4_encrypt); + return 1; + } + + while (len >= MAXBITCHUNK) { + CRYPTO_cfb128_1_encrypt(in, out, MAXBITCHUNK * 8, &sms4_key->ks, + ctx->iv, &ctx->num, ctx->encrypt, (block128_f)sms4_encrypt); + len -= MAXBITCHUNK; + } + + if (len) { + CRYPTO_cfb128_1_encrypt(in, out, len * 8, &sms4_key->ks, + ctx->iv, &ctx->num, ctx->encrypt, (block128_f)sms4_encrypt); + } + + return 1; +} + +const EVP_CIPHER sms4_cfb1 = { + NID_sms4_cfb1, + SMS4_BLOCK_SIZE, + SMS4_KEY_LENGTH, + SMS4_IV_LENGTH, + EVP_CIPH_CTR_MODE, + sms4_init_key, + sms4_cfb1_cipher, + NULL, + sizeof(EVP_SMS4_KEY), + NULL,NULL,NULL,NULL, +}; + +const EVP_CIPHER *EVP_sms4_cfb1(void) +{ + return &sms4_cfb1; +} + +static int sms4_cfb8_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t len) +{ + EVP_SMS4_KEY *sms4_key = (EVP_SMS4_KEY *)ctx->cipher_data; + + CRYPTO_cfb128_8_encrypt(in, out, len, &sms4_key->ks, + ctx->iv, &ctx->num, ctx->encrypt, (block128_f)sms4_encrypt); + + return 1; +} + +const EVP_CIPHER sms4_cfb8 = { + NID_sms4_cfb8, + SMS4_BLOCK_SIZE, + SMS4_KEY_LENGTH, + SMS4_IV_LENGTH, + EVP_CIPH_CTR_MODE, + sms4_init_key, + sms4_cfb8_cipher, + NULL, + sizeof(EVP_SMS4_KEY), + NULL,NULL,NULL,NULL, +}; + +const EVP_CIPHER *EVP_sms4_cfb8(void) +{ + return &sms4_cfb8; +} + +static int sms4_ctr_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t len) +{ + unsigned int num = ctx->num; + EVP_SMS4_KEY *sms4 = (EVP_SMS4_KEY *)ctx->cipher_data; + + CRYPTO_ctr128_encrypt_ctr32(in, out, len, &sms4->ks, ctx->iv, ctx->buf, + &num, (ctr128_f)sms4_encrypt); + + ctx->num = (size_t)num; + return 1; +} + +const EVP_CIPHER sms4_ctr = { + NID_sms4_ctr, + SMS4_BLOCK_SIZE, + SMS4_KEY_LENGTH, + SMS4_IV_LENGTH, + EVP_CIPH_CTR_MODE, + sms4_init_key, + sms4_ctr_cipher, + NULL, /* cleanup() */ + sizeof(EVP_SMS4_KEY), + NULL,NULL,NULL,NULL, +}; + +const EVP_CIPHER *EVP_sms4_ctr(void) +{ + return &sms4_ctr; +} +#endif /* OPENSSL_NO_SMS4 */ diff --git a/crypto/evp/e_sms4_ccm.c b/crypto/evp/e_sms4_ccm.c new file mode 100644 index 00000000..fa3e3820 --- /dev/null +++ b/crypto/evp/e_sms4_ccm.c @@ -0,0 +1,340 @@ +/* ==================================================================== + * Copyright (c) 2014 - 2017 The GmSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the GmSSL Project. + * (http://gmssl.org/)" + * + * 4. The name "GmSSL Project" must not be used to endorse or promote + * products derived from this software without prior written + * permission. For written permission, please contact + * guanzhi1980@gmail.com. + * + * 5. Products derived from this software may not be called "GmSSL" + * nor may "GmSSL" appear in their names without prior written + * permission of the GmSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the GmSSL Project + * (http://gmssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE GmSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE GmSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ + /* + * Copyright 2001-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include + +#include +#include +#include +#include "evp_locl.h" +# include "internal/evp_int.h" +#include "../modes/modes_lcl.h" + +#ifndef OPENSSL_NO_SMS4 + +#include + +typedef struct { + union { + double align; + sms4_key_t ks; + } ks; /* SMS4 key schedule to use */ + int key_set; /* Set if key initialised */ + int iv_set; /* Set if an iv is set */ + int tag_set; /* Set if tag is valid */ + int len_set; /* Set if message length set */ + int L, M; /* L and M parameters from RFC3610 */ + int tls_aad_len; /* TLS AAD length */ + CCM128_CONTEXT ccm; + ccm128_f str; +} EVP_SMS4_CCM_CTX; + +static int sms4_ccm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr) +{ + EVP_SMS4_CCM_CTX *cctx = EVP_C_DATA(EVP_SMS4_CCM_CTX,c); + switch (type) { + case EVP_CTRL_INIT: + cctx->key_set = 0; + cctx->iv_set = 0; + cctx->L = 8; + cctx->M = 12; + cctx->tag_set = 0; + cctx->len_set = 0; + cctx->tls_aad_len = -1; + return 1; + + case EVP_CTRL_AEAD_TLS1_AAD: + /* Save the AAD for later use */ + if (arg != EVP_AEAD_TLS1_AAD_LEN) + return 0; + memcpy(EVP_CIPHER_CTX_buf_noconst(c), ptr, arg); + cctx->tls_aad_len = arg; + { + uint16_t len = + EVP_CIPHER_CTX_buf_noconst(c)[arg - 2] << 8 + | EVP_CIPHER_CTX_buf_noconst(c)[arg - 1]; + /* Correct length for explicit IV */ + len -= EVP_CCM_TLS_EXPLICIT_IV_LEN; + /* If decrypting correct for tag too */ + if (!EVP_CIPHER_CTX_encrypting(c)) + len -= cctx->M; + EVP_CIPHER_CTX_buf_noconst(c)[arg - 2] = len >> 8; + EVP_CIPHER_CTX_buf_noconst(c)[arg - 1] = len & 0xff; + } + /* Extra padding: tag appended to record */ + return cctx->M; + + case EVP_CTRL_CCM_SET_IV_FIXED: + /* Sanity check length */ + if (arg != EVP_CCM_TLS_FIXED_IV_LEN) + return 0; + /* Just copy to first part of IV */ + memcpy(EVP_CIPHER_CTX_iv_noconst(c), ptr, arg); + return 1; + + case EVP_CTRL_AEAD_SET_IVLEN: + arg = 15 - arg; + case EVP_CTRL_CCM_SET_L: + if (arg < 2 || arg > 8) + return 0; + cctx->L = arg; + return 1; + + case EVP_CTRL_AEAD_SET_TAG: + if ((arg & 1) || arg < 4 || arg > 16) + return 0; + if (EVP_CIPHER_CTX_encrypting(c) && ptr) + return 0; + if (ptr) { + cctx->tag_set = 1; + memcpy(EVP_CIPHER_CTX_buf_noconst(c), ptr, arg); + } + cctx->M = arg; + return 1; + + case EVP_CTRL_AEAD_GET_TAG: + if (!EVP_CIPHER_CTX_encrypting(c) || !cctx->tag_set) + return 0; + if (!CRYPTO_ccm128_tag(&cctx->ccm, ptr, (size_t)arg)) + return 0; + cctx->tag_set = 0; + cctx->iv_set = 0; + cctx->len_set = 0; + return 1; + + case EVP_CTRL_COPY: + { + EVP_CIPHER_CTX *out = ptr; + EVP_SMS4_CCM_CTX *cctx_out = EVP_C_DATA(EVP_SMS4_CCM_CTX,out); + if (cctx->ccm.key) { + if (cctx->ccm.key != &cctx->ks) + return 0; + cctx_out->ccm.key = &cctx_out->ks; + } + return 1; + } + + default: + return -1; + + } +} + +static int sms4_ccm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc) +{ + EVP_SMS4_CCM_CTX *cctx = EVP_C_DATA(EVP_SMS4_CCM_CTX,ctx); + if (!iv && !key) + return 1; + if (key) + do { + sms4_set_encrypt_key(&cctx->ks.ks, key); + CRYPTO_ccm128_init(&cctx->ccm, cctx->M, cctx->L, + &cctx->ks, (block128_f) sms4_encrypt); + cctx->str = NULL; + cctx->key_set = 1; + } while (0); + if (iv) { + memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), iv, 15 - cctx->L); + cctx->iv_set = 1; + } + return 1; +} + +static int sms4_ccm_tls_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t len) +{ + EVP_SMS4_CCM_CTX *cctx = EVP_C_DATA(EVP_SMS4_CCM_CTX,ctx); + CCM128_CONTEXT *ccm = &cctx->ccm; + /* Encrypt/decrypt must be performed in place */ + if (out != in || len < (EVP_CCM_TLS_EXPLICIT_IV_LEN + (size_t)cctx->M)) + return -1; + /* If encrypting set explicit IV from sequence number (start of AAD) */ + if (EVP_CIPHER_CTX_encrypting(ctx)) + memcpy(out, EVP_CIPHER_CTX_buf_noconst(ctx), + EVP_CCM_TLS_EXPLICIT_IV_LEN); + /* Get rest of IV from explicit IV */ + memcpy(EVP_CIPHER_CTX_iv_noconst(ctx) + EVP_CCM_TLS_FIXED_IV_LEN, in, + EVP_CCM_TLS_EXPLICIT_IV_LEN); + /* Correct length value */ + len -= EVP_CCM_TLS_EXPLICIT_IV_LEN + cctx->M; + if (CRYPTO_ccm128_setiv(ccm, EVP_CIPHER_CTX_iv_noconst(ctx), 15 - cctx->L, + len)) + return -1; + /* Use saved AAD */ + CRYPTO_ccm128_aad(ccm, EVP_CIPHER_CTX_buf_noconst(ctx), cctx->tls_aad_len); + /* Fix buffer to point to payload */ + in += EVP_CCM_TLS_EXPLICIT_IV_LEN; + out += EVP_CCM_TLS_EXPLICIT_IV_LEN; + if (EVP_CIPHER_CTX_encrypting(ctx)) { + if (cctx->str ? CRYPTO_ccm128_encrypt_ccm64(ccm, in, out, len, + cctx->str) : + CRYPTO_ccm128_encrypt(ccm, in, out, len)) + return -1; + if (!CRYPTO_ccm128_tag(ccm, out + len, cctx->M)) + return -1; + return len + EVP_CCM_TLS_EXPLICIT_IV_LEN + cctx->M; + } else { + if (cctx->str ? !CRYPTO_ccm128_decrypt_ccm64(ccm, in, out, len, + cctx->str) : + !CRYPTO_ccm128_decrypt(ccm, in, out, len)) { + unsigned char tag[16]; + if (CRYPTO_ccm128_tag(ccm, tag, cctx->M)) { + if (!CRYPTO_memcmp(tag, in + len, cctx->M)) + return len; + } + } + OPENSSL_cleanse(out, len); + return -1; + } +} + +static int sms4_ccm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t len) +{ + EVP_SMS4_CCM_CTX *cctx = EVP_C_DATA(EVP_SMS4_CCM_CTX,ctx); + CCM128_CONTEXT *ccm = &cctx->ccm; + /* If not set up, return error */ + if (!cctx->key_set) + return -1; + + if (cctx->tls_aad_len >= 0) + return sms4_ccm_tls_cipher(ctx, out, in, len); + + if (!cctx->iv_set) + return -1; + + if (!EVP_CIPHER_CTX_encrypting(ctx) && !cctx->tag_set) + return -1; + if (!out) { + if (!in) { + if (CRYPTO_ccm128_setiv(ccm, EVP_CIPHER_CTX_iv_noconst(ctx), + 15 - cctx->L, len)) + return -1; + cctx->len_set = 1; + return len; + } + /* If have AAD need message length */ + if (!cctx->len_set && len) + return -1; + CRYPTO_ccm128_aad(ccm, in, len); + return len; + } + /* EVP_*Final() doesn't return any data */ + if (!in) + return 0; + /* If not set length yet do it */ + if (!cctx->len_set) { + if (CRYPTO_ccm128_setiv(ccm, EVP_CIPHER_CTX_iv_noconst(ctx), + 15 - cctx->L, len)) + return -1; + cctx->len_set = 1; + } + if (EVP_CIPHER_CTX_encrypting(ctx)) { + if (cctx->str ? CRYPTO_ccm128_encrypt_ccm64(ccm, in, out, len, + cctx->str) : + CRYPTO_ccm128_encrypt(ccm, in, out, len)) + return -1; + cctx->tag_set = 1; + return len; + } else { + int rv = -1; + if (cctx->str ? !CRYPTO_ccm128_decrypt_ccm64(ccm, in, out, len, + cctx->str) : + !CRYPTO_ccm128_decrypt(ccm, in, out, len)) { + unsigned char tag[16]; + if (CRYPTO_ccm128_tag(ccm, tag, cctx->M)) { + if (!CRYPTO_memcmp(tag, EVP_CIPHER_CTX_buf_noconst(ctx), + cctx->M)) + rv = len; + } + } + if (rv == -1) + OPENSSL_cleanse(out, len); + cctx->iv_set = 0; + cctx->tag_set = 0; + cctx->len_set = 0; + return rv; + } +} + +#define SMS4_CCM_BLOCK_SIZE 1 +#define SMS4_CCM_IV_LENGTH 12 + +#define SMS4_CCM_FLAGS (EVP_CIPH_FLAG_DEFAULT_ASN1 \ + | EVP_CIPH_CUSTOM_IV | EVP_CIPH_FLAG_CUSTOM_CIPHER \ + | EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CTRL_INIT \ + | EVP_CIPH_CUSTOM_COPY \ + | EVP_CIPH_FLAG_AEAD_CIPHER) + +static const EVP_CIPHER sms4_ccm = { + NID_sms4_ccm, + SMS4_CCM_BLOCK_SIZE, + SMS4_KEY_LENGTH, + SMS4_CCM_IV_LENGTH, + SMS4_CCM_FLAGS, + sms4_ccm_init_key, + sms4_ccm_cipher, + NULL, + sizeof(EVP_SMS4_CCM_CTX), + NULL, NULL, sms4_ccm_ctrl, NULL +}; + +const EVP_CIPHER *EVP_sms4_ccm(void) { + return &sms4_ccm; +} +#endif /* OPENSSL_NO_SMS4 */ diff --git a/crypto/evp/e_sms4_gcm.c b/crypto/evp/e_sms4_gcm.c new file mode 100644 index 00000000..a3bd41aa --- /dev/null +++ b/crypto/evp/e_sms4_gcm.c @@ -0,0 +1,463 @@ +/* ==================================================================== + * Copyright (c) 2014 - 2017 The GmSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the GmSSL Project. + * (http://gmssl.org/)" + * + * 4. The name "GmSSL Project" must not be used to endorse or promote + * products derived from this software without prior written + * permission. For written permission, please contact + * guanzhi1980@gmail.com. + * + * 5. Products derived from this software may not be called "GmSSL" + * nor may "GmSSL" appear in their names without prior written + * permission of the GmSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the GmSSL Project + * (http://gmssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE GmSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE GmSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ + /* + * Copyright 2001-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include + +#include +#include +#include +#include +#include "evp_locl.h" +# include "internal/evp_int.h" +#include "../modes/modes_lcl.h" + +#ifndef OPENSSL_NO_SMS4 + +#include + +typedef struct { + union { + double align; + sms4_key_t ks; + } ks; /* SMS4 key schedule to use */ + int key_set; /* Set if key initialised */ + int iv_set; /* Set if an iv is set */ + GCM128_CONTEXT gcm; + unsigned char *iv; /* Temporary IV store */ + int ivlen; /* IV length */ + int taglen; + int iv_gen; /* It is OK to generate IVs */ + int tls_aad_len; /* TLS AAD length */ + ctr128_f ctr; +} EVP_SMS4_GCM_CTX; + + +static int sms4_gcm_cleanup(EVP_CIPHER_CTX *c) +{ + EVP_SMS4_GCM_CTX *gctx = EVP_C_DATA(EVP_SMS4_GCM_CTX,c); + OPENSSL_cleanse(&gctx->gcm, sizeof(gctx->gcm)); + if (gctx->iv != EVP_CIPHER_CTX_iv_noconst(c)) + OPENSSL_free(gctx->iv); + return 1; +} + +/* increment counter (64-bit int) by 1 */ +static void ctr64_inc(unsigned char *counter) +{ + int n = 8; + unsigned char c; + + do { + --n; + c = counter[n]; + ++c; + counter[n] = c; + if (c) + return; + } while (n); +} + +static int sms4_gcm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr) +{ + EVP_SMS4_GCM_CTX *gctx = EVP_C_DATA(EVP_SMS4_GCM_CTX,c); + switch (type) { + case EVP_CTRL_INIT: + gctx->key_set = 0; + gctx->iv_set = 0; + gctx->ivlen = EVP_CIPHER_CTX_iv_length(c); + gctx->iv = EVP_CIPHER_CTX_iv_noconst(c); + gctx->taglen = -1; + gctx->iv_gen = 0; + gctx->tls_aad_len = -1; + return 1; + + case EVP_CTRL_AEAD_SET_IVLEN: + if (arg <= 0) + return 0; + /* Allocate memory for IV if needed */ + if ((arg > EVP_MAX_IV_LENGTH) && (arg > gctx->ivlen)) { + if (gctx->iv != EVP_CIPHER_CTX_iv_noconst(c)) + OPENSSL_free(gctx->iv); + gctx->iv = OPENSSL_malloc(arg); + if (gctx->iv == NULL) + return 0; + } + gctx->ivlen = arg; + return 1; + + case EVP_CTRL_AEAD_SET_TAG: + if (arg <= 0 || arg > 16 || EVP_CIPHER_CTX_encrypting(c)) + return 0; + memcpy(EVP_CIPHER_CTX_buf_noconst(c), ptr, arg); + gctx->taglen = arg; + return 1; + + case EVP_CTRL_AEAD_GET_TAG: + if (arg <= 0 || arg > 16 || !EVP_CIPHER_CTX_encrypting(c) + || gctx->taglen < 0) + return 0; + memcpy(ptr, EVP_CIPHER_CTX_buf_noconst(c), arg); + return 1; + + case EVP_CTRL_GCM_SET_IV_FIXED: + /* Special case: -1 length restores whole IV */ + if (arg == -1) { + memcpy(gctx->iv, ptr, gctx->ivlen); + gctx->iv_gen = 1; + return 1; + } + /* + * Fixed field must be at least 4 bytes and invocation field at least + * 8. + */ + if ((arg < 4) || (gctx->ivlen - arg) < 8) + return 0; + if (arg) + memcpy(gctx->iv, ptr, arg); + if (EVP_CIPHER_CTX_encrypting(c) + && RAND_bytes(gctx->iv + arg, gctx->ivlen - arg) <= 0) + return 0; + gctx->iv_gen = 1; + return 1; + + case EVP_CTRL_GCM_IV_GEN: + if (gctx->iv_gen == 0 || gctx->key_set == 0) + return 0; + CRYPTO_gcm128_setiv(&gctx->gcm, gctx->iv, gctx->ivlen); + if (arg <= 0 || arg > gctx->ivlen) + arg = gctx->ivlen; + memcpy(ptr, gctx->iv + gctx->ivlen - arg, arg); + /* + * Invocation field will be at least 8 bytes in size and so no need + * to check wrap around or increment more than last 8 bytes. + */ + ctr64_inc(gctx->iv + gctx->ivlen - 8); + gctx->iv_set = 1; + return 1; + + case EVP_CTRL_GCM_SET_IV_INV: + if (gctx->iv_gen == 0 || gctx->key_set == 0 + || EVP_CIPHER_CTX_encrypting(c)) + return 0; + memcpy(gctx->iv + gctx->ivlen - arg, ptr, arg); + CRYPTO_gcm128_setiv(&gctx->gcm, gctx->iv, gctx->ivlen); + gctx->iv_set = 1; + return 1; + + case EVP_CTRL_AEAD_TLS1_AAD: + /* Save the AAD for later use */ + if (arg != EVP_AEAD_TLS1_AAD_LEN) + return 0; + memcpy(EVP_CIPHER_CTX_buf_noconst(c), ptr, arg); + gctx->tls_aad_len = arg; + { + unsigned int len = + EVP_CIPHER_CTX_buf_noconst(c)[arg - 2] << 8 + | EVP_CIPHER_CTX_buf_noconst(c)[arg - 1]; + /* Correct length for explicit IV */ + len -= EVP_GCM_TLS_EXPLICIT_IV_LEN; + /* If decrypting correct for tag too */ + if (!EVP_CIPHER_CTX_encrypting(c)) + len -= EVP_GCM_TLS_TAG_LEN; + EVP_CIPHER_CTX_buf_noconst(c)[arg - 2] = len >> 8; + EVP_CIPHER_CTX_buf_noconst(c)[arg - 1] = len & 0xff; + } + /* Extra padding: tag appended to record */ + return EVP_GCM_TLS_TAG_LEN; + + case EVP_CTRL_COPY: + { + EVP_CIPHER_CTX *out = ptr; + EVP_SMS4_GCM_CTX *gctx_out = EVP_C_DATA(EVP_SMS4_GCM_CTX,out); + if (gctx->gcm.key) { + if (gctx->gcm.key != &gctx->ks) + return 0; + gctx_out->gcm.key = &gctx_out->ks; + } + if (gctx->iv == EVP_CIPHER_CTX_iv_noconst(c)) + gctx_out->iv = EVP_CIPHER_CTX_iv_noconst(out); + else { + gctx_out->iv = OPENSSL_malloc(gctx->ivlen); + if (gctx_out->iv == NULL) + return 0; + memcpy(gctx_out->iv, gctx->iv, gctx->ivlen); + } + return 1; + } + + default: + return -1; + + } +} + +static int sms4_gcm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc) +{ + EVP_SMS4_GCM_CTX *gctx = EVP_C_DATA(EVP_SMS4_GCM_CTX,ctx); + if (!iv && !key) + return 1; + if (key) { + do { + (void)0; /* terminate potentially open 'else' */ + + sms4_set_encrypt_key(&gctx->ks.ks, key); + CRYPTO_gcm128_init(&gctx->gcm, &gctx->ks, + (block128_f)sms4_encrypt); + gctx->ctr = NULL; + } while (0); + + /* + * If we have an iv can set it directly, otherwise use saved IV. + */ + if (iv == NULL && gctx->iv_set) + iv = gctx->iv; + if (iv) { + CRYPTO_gcm128_setiv(&gctx->gcm, iv, gctx->ivlen); + gctx->iv_set = 1; + } + gctx->key_set = 1; + } else { + /* If key set use IV, otherwise copy */ + if (gctx->key_set) + CRYPTO_gcm128_setiv(&gctx->gcm, iv, gctx->ivlen); + else + memcpy(gctx->iv, iv, gctx->ivlen); + gctx->iv_set = 1; + gctx->iv_gen = 0; + } + return 1; +} + +/* + * Handle TLS GCM packet format. This consists of the last portion of the IV + * followed by the payload and finally the tag. On encrypt generate IV, + * encrypt payload and write the tag. On verify retrieve IV, decrypt payload + * and verify tag. + */ + +static int sms4_gcm_tls_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t len) +{ + EVP_SMS4_GCM_CTX *gctx = EVP_C_DATA(EVP_SMS4_GCM_CTX,ctx); + int rv = -1; + /* Encrypt/decrypt must be performed in place */ + if (out != in + || len < (EVP_GCM_TLS_EXPLICIT_IV_LEN + EVP_GCM_TLS_TAG_LEN)) + return -1; + /* + * Set IV from start of buffer or generate IV and write to start of + * buffer. + */ + if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CIPHER_CTX_encrypting(ctx) ? + EVP_CTRL_GCM_IV_GEN : EVP_CTRL_GCM_SET_IV_INV, + EVP_GCM_TLS_EXPLICIT_IV_LEN, out) <= 0) + goto err; + /* Use saved AAD */ + if (CRYPTO_gcm128_aad(&gctx->gcm, EVP_CIPHER_CTX_buf_noconst(ctx), + gctx->tls_aad_len)) + goto err; + /* Fix buffer and length to point to payload */ + in += EVP_GCM_TLS_EXPLICIT_IV_LEN; + out += EVP_GCM_TLS_EXPLICIT_IV_LEN; + len -= EVP_GCM_TLS_EXPLICIT_IV_LEN + EVP_GCM_TLS_TAG_LEN; + if (EVP_CIPHER_CTX_encrypting(ctx)) { + /* Encrypt payload */ + if (gctx->ctr) { + size_t bulk = 0; + if (CRYPTO_gcm128_encrypt_ctr32(&gctx->gcm, + in + bulk, + out + bulk, + len - bulk, gctx->ctr)) + goto err; + } else { + size_t bulk = 0; + if (CRYPTO_gcm128_encrypt(&gctx->gcm, + in + bulk, out + bulk, len - bulk)) + goto err; + } + out += len; + /* Finally write tag */ + CRYPTO_gcm128_tag(&gctx->gcm, out, EVP_GCM_TLS_TAG_LEN); + rv = len + EVP_GCM_TLS_EXPLICIT_IV_LEN + EVP_GCM_TLS_TAG_LEN; + } else { + /* Decrypt */ + if (gctx->ctr) { + size_t bulk = 0; + if (CRYPTO_gcm128_decrypt_ctr32(&gctx->gcm, + in + bulk, + out + bulk, + len - bulk, gctx->ctr)) + goto err; + } else { + size_t bulk = 0; + if (CRYPTO_gcm128_decrypt(&gctx->gcm, + in + bulk, out + bulk, len - bulk)) + goto err; + } + /* Retrieve tag */ + CRYPTO_gcm128_tag(&gctx->gcm, EVP_CIPHER_CTX_buf_noconst(ctx), + EVP_GCM_TLS_TAG_LEN); + /* If tag mismatch wipe buffer */ + if (CRYPTO_memcmp(EVP_CIPHER_CTX_buf_noconst(ctx), in + len, + EVP_GCM_TLS_TAG_LEN)) { + OPENSSL_cleanse(out, len); + goto err; + } + rv = len; + } + + err: + gctx->iv_set = 0; + gctx->tls_aad_len = -1; + return rv; +} + +static int sms4_gcm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t len) +{ + EVP_SMS4_GCM_CTX *gctx = EVP_C_DATA(EVP_SMS4_GCM_CTX,ctx); + /* If not set up, return error */ + if (!gctx->key_set) + return -1; + + if (gctx->tls_aad_len >= 0) + return sms4_gcm_tls_cipher(ctx, out, in, len); + + if (!gctx->iv_set) + return -1; + if (in) { + if (out == NULL) { + if (CRYPTO_gcm128_aad(&gctx->gcm, in, len)) + return -1; + } else if (EVP_CIPHER_CTX_encrypting(ctx)) { + if (gctx->ctr) { + size_t bulk = 0; + if (CRYPTO_gcm128_encrypt_ctr32(&gctx->gcm, + in + bulk, + out + bulk, + len - bulk, gctx->ctr)) + return -1; + } else { + size_t bulk = 0; + if (CRYPTO_gcm128_encrypt(&gctx->gcm, + in + bulk, out + bulk, len - bulk)) + return -1; + } + } else { + if (gctx->ctr) { + size_t bulk = 0; + if (CRYPTO_gcm128_decrypt_ctr32(&gctx->gcm, + in + bulk, + out + bulk, + len - bulk, gctx->ctr)) + return -1; + } else { + size_t bulk = 0; + if (CRYPTO_gcm128_decrypt(&gctx->gcm, + in + bulk, out + bulk, len - bulk)) + return -1; + } + } + return len; + } else { + if (!EVP_CIPHER_CTX_encrypting(ctx)) { + if (gctx->taglen < 0) + return -1; + if (CRYPTO_gcm128_finish(&gctx->gcm, + EVP_CIPHER_CTX_buf_noconst(ctx), + gctx->taglen) != 0) + return -1; + gctx->iv_set = 0; + return 0; + } + CRYPTO_gcm128_tag(&gctx->gcm, EVP_CIPHER_CTX_buf_noconst(ctx), 16); + gctx->taglen = 16; + /* Don't reuse the IV */ + gctx->iv_set = 0; + return 0; + } + +} + +#define SMS4_GCM_BLOCK_SIZE 1 +#define SMS4_GCM_IV_LENGTH 12 + +#define SMS4_GCM_FLAGS (EVP_CIPH_FLAG_DEFAULT_ASN1 \ + | EVP_CIPH_CUSTOM_IV | EVP_CIPH_FLAG_CUSTOM_CIPHER \ + | EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CTRL_INIT \ + | EVP_CIPH_CUSTOM_COPY \ + | EVP_CIPH_FLAG_AEAD_CIPHER) + +static const EVP_CIPHER sms4_gcm = { + NID_sms4_gcm, + SMS4_GCM_BLOCK_SIZE, + SMS4_KEY_LENGTH, + SMS4_GCM_IV_LENGTH, + SMS4_GCM_FLAGS, + sms4_gcm_init_key, + sms4_gcm_cipher, + sms4_gcm_cleanup, + sizeof(EVP_SMS4_GCM_CTX), + NULL, NULL, sms4_gcm_ctrl, NULL +}; + +const EVP_CIPHER *EVP_sms4_gcm(void) { + return &sms4_gcm; +} + +#endif /* OPENSSL_NO_SMS4 */ diff --git a/crypto/evp/e_sms4_ocb.c b/crypto/evp/e_sms4_ocb.c new file mode 100644 index 00000000..62066b5c --- /dev/null +++ b/crypto/evp/e_sms4_ocb.c @@ -0,0 +1,373 @@ +/* ==================================================================== + * Copyright (c) 2014 - 2017 The GmSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the GmSSL Project. + * (http://gmssl.org/)" + * + * 4. The name "GmSSL Project" must not be used to endorse or promote + * products derived from this software without prior written + * permission. For written permission, please contact + * guanzhi1980@gmail.com. + * + * 5. Products derived from this software may not be called "GmSSL" + * nor may "GmSSL" appear in their names without prior written + * permission of the GmSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the GmSSL Project + * (http://gmssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE GmSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE GmSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ + /* + * Copyright 2001-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include + +#include +#include +#include +#include "evp_locl.h" +# include "internal/evp_int.h" +#include "../modes/modes_lcl.h" + +#ifndef OPENSSL_NO_SMS4 + +# include + +# ifndef OPENSSL_NO_OCB + +typedef struct { + union { + double align; + sms4_key_t ks; + } ksenc; /* SMS4 key schedule to use for encryption */ + union { + double align; + sms4_key_t ks; + } ksdec; /* SMS4 key schedule to use for decryption */ + int key_set; /* Set if key initialised */ + int iv_set; /* Set if an iv is set */ + OCB128_CONTEXT ocb; + unsigned char *iv; /* Temporary IV store */ + unsigned char tag[16]; + unsigned char data_buf[16]; /* Store partial data blocks */ + unsigned char aad_buf[16]; /* Store partial AAD blocks */ + int data_buf_len; + int aad_buf_len; + int ivlen; /* IV length */ + int taglen; +} EVP_SMS4_OCB_CTX; + +static int sms4_ocb_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr) +{ + EVP_SMS4_OCB_CTX *octx = EVP_C_DATA(EVP_SMS4_OCB_CTX,c); + EVP_CIPHER_CTX *newc; + EVP_SMS4_OCB_CTX *new_octx; + + switch (type) { + case EVP_CTRL_INIT: + octx->key_set = 0; + octx->iv_set = 0; + octx->ivlen = EVP_CIPHER_CTX_iv_length(c); + octx->iv = EVP_CIPHER_CTX_iv_noconst(c); + octx->taglen = 16; + octx->data_buf_len = 0; + octx->aad_buf_len = 0; + return 1; + + case EVP_CTRL_AEAD_SET_IVLEN: + /* IV len must be 1 to 15 */ + if (arg <= 0 || arg > 15) + return 0; + + octx->ivlen = arg; + return 1; + + case EVP_CTRL_AEAD_SET_TAG: + if (!ptr) { + /* Tag len must be 0 to 16 */ + if (arg < 0 || arg > 16) + return 0; + + octx->taglen = arg; + return 1; + } + if (arg != octx->taglen || EVP_CIPHER_CTX_encrypting(c)) + return 0; + memcpy(octx->tag, ptr, arg); + return 1; + + case EVP_CTRL_AEAD_GET_TAG: + if (arg != octx->taglen || !EVP_CIPHER_CTX_encrypting(c)) + return 0; + + memcpy(ptr, octx->tag, arg); + return 1; + + case EVP_CTRL_COPY: + newc = (EVP_CIPHER_CTX *)ptr; + new_octx = EVP_C_DATA(EVP_SMS4_OCB_CTX,newc); + return CRYPTO_ocb128_copy_ctx(&new_octx->ocb, &octx->ocb, + &new_octx->ksenc.ks, + &new_octx->ksdec.ks); + + default: + return -1; + + } +} + +static int sms4_ocb_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc) +{ + EVP_SMS4_OCB_CTX *octx = EVP_C_DATA(EVP_SMS4_OCB_CTX,ctx); + if (!iv && !key) + return 1; + if (key) { + do { + /* + * We set both the encrypt and decrypt key here because decrypt + * needs both. We could possibly optimise to remove setting the + * decrypt for an encryption operation. + */ + sms4_set_encrypt_key(&octx->ksenc.ks, key); + sms4_set_decrypt_key(&octx->ksdec.ks, key); + if (!CRYPTO_ocb128_init(&octx->ocb, + &octx->ksenc.ks, &octx->ksdec.ks, + (block128_f)sms4_encrypt, + (block128_f)sms4_encrypt, + NULL)) + return 0; + } + while (0); + + /* + * If we have an iv we can set it directly, otherwise use saved IV. + */ + if (iv == NULL && octx->iv_set) + iv = octx->iv; + if (iv) { + if (CRYPTO_ocb128_setiv(&octx->ocb, iv, octx->ivlen, octx->taglen) + != 1) + return 0; + octx->iv_set = 1; + } + octx->key_set = 1; + } else { + /* If key set use IV, otherwise copy */ + if (octx->key_set) + CRYPTO_ocb128_setiv(&octx->ocb, iv, octx->ivlen, octx->taglen); + else + memcpy(octx->iv, iv, octx->ivlen); + octx->iv_set = 1; + } + return 1; +} + +static int sms4_ocb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t len) +{ + unsigned char *buf; + int *buf_len; + int written_len = 0; + size_t trailing_len; + EVP_SMS4_OCB_CTX *octx = EVP_C_DATA(EVP_SMS4_OCB_CTX,ctx); + + /* If IV or Key not set then return error */ + if (!octx->iv_set) + return -1; + + if (!octx->key_set) + return -1; + + if (in) { + /* + * Need to ensure we are only passing full blocks to low level OCB + * routines. We do it here rather than in EVP_EncryptUpdate/ + * EVP_DecryptUpdate because we need to pass full blocks of AAD too + * and those routines don't support that + */ + + /* Are we dealing with AAD or normal data here? */ + if (out == NULL) { + buf = octx->aad_buf; + buf_len = &(octx->aad_buf_len); + } else { + buf = octx->data_buf; + buf_len = &(octx->data_buf_len); + } + + /* + * If we've got a partially filled buffer from a previous call then + * use that data first + */ + if (*buf_len) { + unsigned int remaining; + + remaining = 16 - (*buf_len); + if (remaining > len) { + memcpy(buf + (*buf_len), in, len); + *(buf_len) += len; + return 0; + } + memcpy(buf + (*buf_len), in, remaining); + + /* + * If we get here we've filled the buffer, so process it + */ + len -= remaining; + in += remaining; + if (out == NULL) { + if (!CRYPTO_ocb128_aad(&octx->ocb, buf, 16)) + return -1; + } else if (EVP_CIPHER_CTX_encrypting(ctx)) { + if (!CRYPTO_ocb128_encrypt(&octx->ocb, buf, out, 16)) + return -1; + } else { + if (!CRYPTO_ocb128_decrypt(&octx->ocb, buf, out, 16)) + return -1; + } + written_len = 16; + *buf_len = 0; + } + + /* Do we have a partial block to handle at the end? */ + trailing_len = len % 16; + + /* + * If we've got some full blocks to handle, then process these first + */ + if (len != trailing_len) { + if (out == NULL) { + if (!CRYPTO_ocb128_aad(&octx->ocb, in, len - trailing_len)) + return -1; + } else if (EVP_CIPHER_CTX_encrypting(ctx)) { + if (!CRYPTO_ocb128_encrypt + (&octx->ocb, in, out, len - trailing_len)) + return -1; + } else { + if (!CRYPTO_ocb128_decrypt + (&octx->ocb, in, out, len - trailing_len)) + return -1; + } + written_len += len - trailing_len; + in += len - trailing_len; + } + + /* Handle any trailing partial block */ + if (trailing_len) { + memcpy(buf, in, trailing_len); + *buf_len = trailing_len; + } + + return written_len; + } else { + /* + * First of all empty the buffer of any partial block that we might + * have been provided - both for data and AAD + */ + if (octx->data_buf_len) { + if (EVP_CIPHER_CTX_encrypting(ctx)) { + if (!CRYPTO_ocb128_encrypt(&octx->ocb, octx->data_buf, out, + octx->data_buf_len)) + return -1; + } else { + if (!CRYPTO_ocb128_decrypt(&octx->ocb, octx->data_buf, out, + octx->data_buf_len)) + return -1; + } + written_len = octx->data_buf_len; + octx->data_buf_len = 0; + } + if (octx->aad_buf_len) { + if (!CRYPTO_ocb128_aad + (&octx->ocb, octx->aad_buf, octx->aad_buf_len)) + return -1; + octx->aad_buf_len = 0; + } + /* If decrypting then verify */ + if (!EVP_CIPHER_CTX_encrypting(ctx)) { + if (octx->taglen < 0) + return -1; + if (CRYPTO_ocb128_finish(&octx->ocb, + octx->tag, octx->taglen) != 0) + return -1; + octx->iv_set = 0; + return written_len; + } + /* If encrypting then just get the tag */ + if (CRYPTO_ocb128_tag(&octx->ocb, octx->tag, 16) != 1) + return -1; + /* Don't reuse the IV */ + octx->iv_set = 0; + return written_len; + } +} + +static int sms4_ocb_cleanup(EVP_CIPHER_CTX *c) +{ + EVP_SMS4_OCB_CTX *octx = EVP_C_DATA(EVP_SMS4_OCB_CTX,c); + CRYPTO_ocb128_cleanup(&octx->ocb); + return 1; +} + +#define SMS4_OCB_IV_LENGTH 12 + +#define SMS4_OCB_FLAGS (EVP_CIPH_FLAG_DEFAULT_ASN1 \ + | EVP_CIPH_CUSTOM_IV | EVP_CIPH_FLAG_CUSTOM_CIPHER \ + | EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CTRL_INIT \ + | EVP_CIPH_CUSTOM_COPY \ + | EVP_CIPH_FLAG_AEAD_CIPHER) + +static const EVP_CIPHER sms4_ocb = { + NID_sms4_ocb, + SMS4_BLOCK_SIZE, + SMS4_KEY_LENGTH, + SMS4_OCB_IV_LENGTH, + SMS4_OCB_FLAGS, + sms4_ocb_init_key, + sms4_ocb_cipher, + sms4_ocb_cleanup, + sizeof(EVP_SMS4_OCB_CTX), + NULL, NULL, sms4_ocb_ctrl, NULL +}; + +const EVP_CIPHER *EVP_sms4_ocb(void) { + return &sms4_ocb; +} +# endif /* OPENSSL_NO_OCB */ +#endif /* OPENSSL_NO_SMS4 */ diff --git a/crypto/evp/e_sms4_wrap.c b/crypto/evp/e_sms4_wrap.c new file mode 100644 index 00000000..c6a1f81e --- /dev/null +++ b/crypto/evp/e_sms4_wrap.c @@ -0,0 +1,188 @@ +/* ==================================================================== + * Copyright (c) 2014 - 2017 The GmSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the GmSSL Project. + * (http://gmssl.org/)" + * + * 4. The name "GmSSL Project" must not be used to endorse or promote + * products derived from this software without prior written + * permission. For written permission, please contact + * guanzhi1980@gmail.com. + * + * 5. Products derived from this software may not be called "GmSSL" + * nor may "GmSSL" appear in their names without prior written + * permission of the GmSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the GmSSL Project + * (http://gmssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE GmSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE GmSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ + /* + * Copyright 2001-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include + +#include +#include +#include +#include "evp_locl.h" +# include "internal/evp_int.h" +#include "../modes/modes_lcl.h" + +#ifndef OPENSSL_NO_SMS4 +# include + +typedef struct { + union { + double align; + sms4_key_t ks; + } ks; + /* Indicates if IV has been set */ + unsigned char *iv; +} EVP_SMS4_WRAP_CTX; + +static int sms4_wrap_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc) +{ + EVP_SMS4_WRAP_CTX *wctx = EVP_C_DATA(EVP_SMS4_WRAP_CTX,ctx); + if (!iv && !key) + return 1; + if (key) { + if (EVP_CIPHER_CTX_encrypting(ctx)) + sms4_set_encrypt_key(&wctx->ks.ks, key); + else + sms4_set_decrypt_key(&wctx->ks.ks, key); + if (!iv) + wctx->iv = NULL; + } + if (iv) { + memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), iv, EVP_CIPHER_CTX_iv_length(ctx)); + wctx->iv = EVP_CIPHER_CTX_iv_noconst(ctx); + } + return 1; +} + +static int sms4_wrap_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t inlen) +{ + EVP_SMS4_WRAP_CTX *wctx = EVP_C_DATA(EVP_SMS4_WRAP_CTX,ctx); + size_t rv; + /* SMS4 wrap with padding has IV length of 4, without padding 8 */ + int pad = EVP_CIPHER_CTX_iv_length(ctx) == 4; + /* No final operation so always return zero length */ + if (!in) + return 0; + /* Input length must always be non-zero */ + if (!inlen) + return -1; + /* If decrypting need at least 16 bytes and multiple of 8 */ + if (!EVP_CIPHER_CTX_encrypting(ctx) && (inlen < 16 || inlen & 0x7)) + return -1; + /* If not padding input must be multiple of 8 */ + if (!pad && inlen & 0x7) + return -1; + if (!out) { + if (EVP_CIPHER_CTX_encrypting(ctx)) { + /* If padding round up to multiple of 8 */ + if (pad) + inlen = (inlen + 7) / 8 * 8; + /* 8 byte prefix */ + return inlen + 8; + } else { + /* + * If not padding output will be exactly 8 bytes smaller than + * input. If padding it will be at least 8 bytes smaller but we + * don't know how much. + */ + return inlen - 8; + } + } + if (pad) { + if (EVP_CIPHER_CTX_encrypting(ctx)) + rv = CRYPTO_128_wrap_pad(&wctx->ks.ks, wctx->iv, + out, in, inlen, + (block128_f)sms4_encrypt); + else + rv = CRYPTO_128_unwrap_pad(&wctx->ks.ks, wctx->iv, + out, in, inlen, + (block128_f)sms4_encrypt); + } else { + if (EVP_CIPHER_CTX_encrypting(ctx)) + rv = CRYPTO_128_wrap(&wctx->ks.ks, wctx->iv, + out, in, inlen, (block128_f)sms4_encrypt); + else + rv = CRYPTO_128_unwrap(&wctx->ks.ks, wctx->iv, + out, in, inlen, (block128_f)sms4_encrypt); + } + return rv ? (int)rv : -1; +} + +#define SMS4_WRAP_FLAGS (EVP_CIPH_WRAP_MODE \ + | EVP_CIPH_CUSTOM_IV | EVP_CIPH_FLAG_CUSTOM_CIPHER \ + | EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_FLAG_DEFAULT_ASN1) + + + +static const EVP_CIPHER sms4_wrap = { + NID_sms4_wrap, + 8, 16, 8, SMS4_WRAP_FLAGS, + sms4_wrap_init_key, sms4_wrap_cipher, + NULL, + sizeof(EVP_SMS4_WRAP_CTX), + NULL, NULL, NULL, NULL +}; + +const EVP_CIPHER *EVP_sms4_wrap(void) +{ + return &sms4_wrap; +} + +static const EVP_CIPHER sms4_wrap_pad = { + NID_sms4_wrap_pad, + 8, 16, 4, SMS4_WRAP_FLAGS, + sms4_wrap_init_key, sms4_wrap_cipher, + NULL, + sizeof(EVP_SMS4_WRAP_CTX), + NULL, NULL, NULL, NULL +}; + +const EVP_CIPHER *EVP_sms4_wrap_pad(void) +{ + return &sms4_wrap_pad; +} +#endif /* OPENSSL_NO_SMS4 */ diff --git a/crypto/evp/e_sms4_xts.c b/crypto/evp/e_sms4_xts.c new file mode 100644 index 00000000..3e2ddf43 --- /dev/null +++ b/crypto/evp/e_sms4_xts.c @@ -0,0 +1,183 @@ +/* ==================================================================== + * Copyright (c) 2014 - 2017 The GmSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the GmSSL Project. + * (http://gmssl.org/)" + * + * 4. The name "GmSSL Project" must not be used to endorse or promote + * products derived from this software without prior written + * permission. For written permission, please contact + * guanzhi1980@gmail.com. + * + * 5. Products derived from this software may not be called "GmSSL" + * nor may "GmSSL" appear in their names without prior written + * permission of the GmSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the GmSSL Project + * (http://gmssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE GmSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE GmSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ + /* + * Copyright 2001-2016 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include + +#include +#include +#include +#include "evp_locl.h" +# include "internal/evp_int.h" +#include "../modes/modes_lcl.h" + +#ifndef OPENSSL_NO_SMS4 +# include + +typedef struct { + union { + double align; + sms4_key_t ks; + } ks1, ks2; /* SMS4 key schedules to use */ + XTS128_CONTEXT xts; + void (*stream) (const unsigned char *in, + unsigned char *out, size_t length, + const sms4_key_t *key1, const sms4_key_t *key2, + const unsigned char iv[16]); +} EVP_SMS4_XTS_CTX; + +static int sms4_xts_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr) +{ + EVP_SMS4_XTS_CTX *xctx = EVP_C_DATA(EVP_SMS4_XTS_CTX,c); + if (type == EVP_CTRL_COPY) { + EVP_CIPHER_CTX *out = ptr; + EVP_SMS4_XTS_CTX *xctx_out = EVP_C_DATA(EVP_SMS4_XTS_CTX,out); + if (xctx->xts.key1) { + if (xctx->xts.key1 != &xctx->ks1) + return 0; + xctx_out->xts.key1 = &xctx_out->ks1; + } + if (xctx->xts.key2) { + if (xctx->xts.key2 != &xctx->ks2) + return 0; + xctx_out->xts.key2 = &xctx_out->ks2; + } + return 1; + } else if (type != EVP_CTRL_INIT) + return -1; + /* key1 and key2 are used as an indicator both key and IV are set */ + xctx->xts.key1 = NULL; + xctx->xts.key2 = NULL; + return 1; +} + +static int sms4_xts_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, + const unsigned char *iv, int enc) +{ + EVP_SMS4_XTS_CTX *xctx = EVP_C_DATA(EVP_SMS4_XTS_CTX,ctx); + if (!iv && !key) + return 1; + + if (key) + do { + xctx->stream = NULL; + /* key_len is two SMS4 keys */ + (void)0; /* terminate potentially open 'else' */ + + if (enc) { + sms4_set_encrypt_key(&xctx->ks1.ks, key); + xctx->xts.block1 = (block128_f)sms4_encrypt; + } else { + sms4_set_decrypt_key(&xctx->ks1.ks, key); + xctx->xts.block1 = (block128_f)sms4_encrypt; + } + + sms4_set_encrypt_key(&xctx->ks2.ks, key + EVP_CIPHER_CTX_key_length(ctx)/2); + xctx->xts.block2 = (block128_f)sms4_encrypt; + + xctx->xts.key1 = &xctx->ks1; + } while (0); + + if (iv) { + xctx->xts.key2 = &xctx->ks2; + memcpy(EVP_CIPHER_CTX_iv_noconst(ctx), iv, 16); + } + + return 1; +} + +static int sms4_xts_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, + const unsigned char *in, size_t len) +{ + EVP_SMS4_XTS_CTX *xctx = EVP_C_DATA(EVP_SMS4_XTS_CTX,ctx); + if (!xctx->xts.key1 || !xctx->xts.key2) + return 0; + if (!out || !in || len < SMS4_BLOCK_SIZE) + return 0; + if (xctx->stream) + (*xctx->stream) (in, out, len, + xctx->xts.key1, xctx->xts.key2, + EVP_CIPHER_CTX_iv_noconst(ctx)); + else if (CRYPTO_xts128_encrypt(&xctx->xts, EVP_CIPHER_CTX_iv_noconst(ctx), + in, out, len, + EVP_CIPHER_CTX_encrypting(ctx))) + return 0; + return 1; +} + +#define SMS4_XTS_BLOCK_SIZE 1 + +#define SMS4_XTS_FLAGS (EVP_CIPH_FLAG_DEFAULT_ASN1 | EVP_CIPH_CUSTOM_IV \ + | EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CTRL_INIT \ + | EVP_CIPH_CUSTOM_COPY) + +static const EVP_CIPHER sms4_xts = { + NID_sms4_xts, + SMS4_XTS_BLOCK_SIZE, + SMS4_KEY_LENGTH, + SMS4_IV_LENGTH, + SMS4_XTS_FLAGS, + sms4_xts_init_key, + sms4_xts_cipher, + NULL, + sizeof(EVP_SMS4_XTS_CTX), + NULL, NULL, sms4_xts_ctrl, NULL +}; + +const EVP_CIPHER *EVP_sms4_xts(void) { + return &sms4_xts; +} +#endif /* OPENSSL_NO_SMS4 */ diff --git a/crypto/sms4/build.info b/crypto/sms4/build.info new file mode 100644 index 00000000..0c9f3d2b --- /dev/null +++ b/crypto/sms4/build.info @@ -0,0 +1,4 @@ +LIBS=../../libcrypto +SOURCE[../../libcrypto]=\ + sms4_common.c sms4_setkey.c sms4_enc.c sms4_enc_nblks.c \ + sms4_ecb.c sms4_cbc.c sms4_cfb.c sms4_ctr.c sms4_ofb.c sms4_wrap.c diff --git a/crypto/sms4/sms4_cbc.c b/crypto/sms4/sms4_cbc.c new file mode 100644 index 00000000..48efa458 --- /dev/null +++ b/crypto/sms4/sms4_cbc.c @@ -0,0 +1,59 @@ +/* ==================================================================== + * Copyright (c) 2014 - 2017 The GmSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the GmSSL Project. + * (http://gmssl.org/)" + * + * 4. The name "GmSSL Project" must not be used to endorse or promote + * products derived from this software without prior written + * permission. For written permission, please contact + * guanzhi1980@gmail.com. + * + * 5. Products derived from this software may not be called "GmSSL" + * nor may "GmSSL" appear in their names without prior written + * permission of the GmSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the GmSSL Project + * (http://gmssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE GmSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE GmSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ + +#include +#include + +void sms4_cbc_encrypt(const unsigned char *in, unsigned char *out, + size_t len, const sms4_key_t *key, unsigned char *iv, int enc) +{ + if (enc) + CRYPTO_cbc128_encrypt(in, out, len, key, iv, (block128_f)sms4_encrypt); + else CRYPTO_cbc128_decrypt(in, out, len, key, iv, (block128_f)sms4_encrypt); +} diff --git a/crypto/sms4/sms4_cfb.c b/crypto/sms4/sms4_cfb.c new file mode 100644 index 00000000..499891d2 --- /dev/null +++ b/crypto/sms4/sms4_cfb.c @@ -0,0 +1,57 @@ +/* ==================================================================== + * Copyright (c) 2014 - 2017 The GmSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the GmSSL Project. + * (http://gmssl.org/)" + * + * 4. The name "GmSSL Project" must not be used to endorse or promote + * products derived from this software without prior written + * permission. For written permission, please contact + * guanzhi1980@gmail.com. + * + * 5. Products derived from this software may not be called "GmSSL" + * nor may "GmSSL" appear in their names without prior written + * permission of the GmSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the GmSSL Project + * (http://gmssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE GmSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE GmSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ + +#include +#include + +void sms4_cfb128_encrypt(const unsigned char *in, unsigned char *out, + size_t len, const sms4_key_t *key, unsigned char *iv, int *num, int enc) +{ + CRYPTO_cfb128_encrypt(in, out, len, key, iv, num, enc, (block128_f)sms4_encrypt); +} diff --git a/crypto/sms4/sms4_common.c b/crypto/sms4/sms4_common.c new file mode 100644 index 00000000..5751f1fa --- /dev/null +++ b/crypto/sms4/sms4_common.c @@ -0,0 +1,103 @@ +/* ==================================================================== + * Copyright (c) 2014 - 2017 The GmSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the GmSSL Project. + * (http://gmssl.org/)" + * + * 4. The name "GmSSL Project" must not be used to endorse or promote + * products derived from this software without prior written + * permission. For written permission, please contact + * guanzhi1980@gmail.com. + * + * 5. Products derived from this software may not be called "GmSSL" + * nor may "GmSSL" appear in their names without prior written + * permission of the GmSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the GmSSL Project + * (http://gmssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE GmSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE GmSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ + +#include +#include "sms4_lcl.h" + +uint8_t SBOX[256] = { + 0xd6, 0x90, 0xe9, 0xfe, 0xcc, 0xe1, 0x3d, 0xb7, + 0x16, 0xb6, 0x14, 0xc2, 0x28, 0xfb, 0x2c, 0x05, + 0x2b, 0x67, 0x9a, 0x76, 0x2a, 0xbe, 0x04, 0xc3, + 0xaa, 0x44, 0x13, 0x26, 0x49, 0x86, 0x06, 0x99, + 0x9c, 0x42, 0x50, 0xf4, 0x91, 0xef, 0x98, 0x7a, + 0x33, 0x54, 0x0b, 0x43, 0xed, 0xcf, 0xac, 0x62, + 0xe4, 0xb3, 0x1c, 0xa9, 0xc9, 0x08, 0xe8, 0x95, + 0x80, 0xdf, 0x94, 0xfa, 0x75, 0x8f, 0x3f, 0xa6, + 0x47, 0x07, 0xa7, 0xfc, 0xf3, 0x73, 0x17, 0xba, + 0x83, 0x59, 0x3c, 0x19, 0xe6, 0x85, 0x4f, 0xa8, + 0x68, 0x6b, 0x81, 0xb2, 0x71, 0x64, 0xda, 0x8b, + 0xf8, 0xeb, 0x0f, 0x4b, 0x70, 0x56, 0x9d, 0x35, + 0x1e, 0x24, 0x0e, 0x5e, 0x63, 0x58, 0xd1, 0xa2, + 0x25, 0x22, 0x7c, 0x3b, 0x01, 0x21, 0x78, 0x87, + 0xd4, 0x00, 0x46, 0x57, 0x9f, 0xd3, 0x27, 0x52, + 0x4c, 0x36, 0x02, 0xe7, 0xa0, 0xc4, 0xc8, 0x9e, + 0xea, 0xbf, 0x8a, 0xd2, 0x40, 0xc7, 0x38, 0xb5, + 0xa3, 0xf7, 0xf2, 0xce, 0xf9, 0x61, 0x15, 0xa1, + 0xe0, 0xae, 0x5d, 0xa4, 0x9b, 0x34, 0x1a, 0x55, + 0xad, 0x93, 0x32, 0x30, 0xf5, 0x8c, 0xb1, 0xe3, + 0x1d, 0xf6, 0xe2, 0x2e, 0x82, 0x66, 0xca, 0x60, + 0xc0, 0x29, 0x23, 0xab, 0x0d, 0x53, 0x4e, 0x6f, + 0xd5, 0xdb, 0x37, 0x45, 0xde, 0xfd, 0x8e, 0x2f, + 0x03, 0xff, 0x6a, 0x72, 0x6d, 0x6c, 0x5b, 0x51, + 0x8d, 0x1b, 0xaf, 0x92, 0xbb, 0xdd, 0xbc, 0x7f, + 0x11, 0xd9, 0x5c, 0x41, 0x1f, 0x10, 0x5a, 0xd8, + 0x0a, 0xc1, 0x31, 0x88, 0xa5, 0xcd, 0x7b, 0xbd, + 0x2d, 0x74, 0xd0, 0x12, 0xb8, 0xe5, 0xb4, 0xb0, + 0x89, 0x69, 0x97, 0x4a, 0x0c, 0x96, 0x77, 0x7e, + 0x65, 0xb9, 0xf1, 0x09, 0xc5, 0x6e, 0xc6, 0x84, + 0x18, 0xf0, 0x7d, 0xec, 0x3a, 0xdc, 0x4d, 0x20, + 0x79, 0xee, 0x5f, 0x3e, 0xd7, 0xcb, 0x39, 0x48, +}; + +uint32_t SBOX32L[256 * 256]; +uint32_t SBOX32H[256 * 256]; + +void sms4_init_sbox32(void) +{ + int i, j; + uint32_t a; + + for (i = 0; i < 256; i++) { + for (j = 0; j < 256; j++) { + a = SBOX[i] << 8 | SBOX[j]; + SBOX32L[(i << 8) + j] = a; + SBOX32H[(i << 8) + j] = a << 16; + } + } +} diff --git a/crypto/sms4/sms4_ctr.c b/crypto/sms4/sms4_ctr.c new file mode 100644 index 00000000..1de3d4ad --- /dev/null +++ b/crypto/sms4/sms4_ctr.c @@ -0,0 +1,59 @@ +/* ==================================================================== + * Copyright (c) 2014 - 2017 The GmSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the GmSSL Project. + * (http://gmssl.org/)" + * + * 4. The name "GmSSL Project" must not be used to endorse or promote + * products derived from this software without prior written + * permission. For written permission, please contact + * guanzhi1980@gmail.com. + * + * 5. Products derived from this software may not be called "GmSSL" + * nor may "GmSSL" appear in their names without prior written + * permission of the GmSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the GmSSL Project + * (http://gmssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE GmSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE GmSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ + +#include +#include + +void sms4_ctr128_encrypt(const unsigned char *in, unsigned char *out, + size_t len, const sms4_key_t *key, unsigned char *iv, + unsigned char ecount_buf[SMS4_BLOCK_SIZE], unsigned int *num) +{ + CRYPTO_ctr128_encrypt(in, out, len, key, iv, ecount_buf, num, + (block128_f)sms4_encrypt); +} diff --git a/crypto/sms4/sms4_ecb.c b/crypto/sms4/sms4_ecb.c new file mode 100644 index 00000000..e00816e8 --- /dev/null +++ b/crypto/sms4/sms4_ecb.c @@ -0,0 +1,59 @@ +/* ==================================================================== + * Copyright (c) 2014 - 2017 The GmSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the GmSSL Project. + * (http://gmssl.org/)" + * + * 4. The name "GmSSL Project" must not be used to endorse or promote + * products derived from this software without prior written + * permission. For written permission, please contact + * guanzhi1980@gmail.com. + * + * 5. Products derived from this software may not be called "GmSSL" + * nor may "GmSSL" appear in their names without prior written + * permission of the GmSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the GmSSL Project + * (http://gmssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE GmSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE GmSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ + +#include +#include + +void sms4_ecb_encrypt(const unsigned char *in, unsigned char *out, + const sms4_key_t *key, int enc) +{ + if (enc) + sms4_encrypt(in, out, key); + else sms4_decrypt(in, out, key); +} diff --git a/crypto/sms4/sms4_enc.c b/crypto/sms4/sms4_enc.c new file mode 100644 index 00000000..f07c0be8 --- /dev/null +++ b/crypto/sms4/sms4_enc.c @@ -0,0 +1,84 @@ +/* ==================================================================== + * Copyright (c) 2014 - 2017 The GmSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the GmSSL Project. + * (http://gmssl.org/)" + * + * 4. The name "GmSSL Project" must not be used to endorse or promote + * products derived from this software without prior written + * permission. For written permission, please contact + * guanzhi1980@gmail.com. + * + * 5. Products derived from this software may not be called "GmSSL" + * nor may "GmSSL" appear in their names without prior written + * permission of the GmSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the GmSSL Project + * (http://gmssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE GmSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE GmSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ + +#include +#include "sms4_lcl.h" + + +#define L32(x) \ + ((x) ^ \ + ROT32((x), 2) ^ \ + ROT32((x), 10) ^ \ + ROT32((x), 18) ^ \ + ROT32((x), 24)) + +#define ROUND(x0, x1, x2, x3, x4, i) \ + x4 = x1 ^ x2 ^ x3 ^ *(rk + i); \ + x4 = S32(x4); \ + x4 = x0 ^ L32(x4) + +void sms4_encrypt(const unsigned char *in, unsigned char *out, const sms4_key_t *key) +{ + const uint32_t *rk = key->rk; + uint32_t x0, x1, x2, x3, x4; + + x0 = GET32(in ); + x1 = GET32(in + 4); + x2 = GET32(in + 8); + x3 = GET32(in + 12); + + ROUNDS(x0, x1, x2, x3, x4); + + PUT32(x0, out ); + PUT32(x4, out + 4); + PUT32(x3, out + 8); + PUT32(x2, out + 12); + + x0 = x1 = x2 = x3 = x4 = 0; +} diff --git a/crypto/sms4/sms4_enc_nblks.c b/crypto/sms4/sms4_enc_nblks.c new file mode 100644 index 00000000..134d2f17 --- /dev/null +++ b/crypto/sms4/sms4_enc_nblks.c @@ -0,0 +1,73 @@ +/* ==================================================================== + * Copyright (c) 2014 - 2017 The GmSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the GmSSL Project. + * (http://gmssl.org/)" + * + * 4. The name "GmSSL Project" must not be used to endorse or promote + * products derived from this software without prior written + * permission. For written permission, please contact + * guanzhi1980@gmail.com. + * + * 5. Products derived from this software may not be called "GmSSL" + * nor may "GmSSL" appear in their names without prior written + * permission of the GmSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the GmSSL Project + * (http://gmssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE GmSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE GmSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ + + +#include + +void sms4_encrypt_init(sms4_key_t *key) +{ +} + +void sms4_encrypt_8blocks(const unsigned char *in, unsigned char *out, const sms4_key_t *key) +{ + sms4_encrypt(in, out, key); + sms4_encrypt(in + 16, out + 16, key); + sms4_encrypt(in + 16 * 2, out + 16 * 2, key); + sms4_encrypt(in + 16 * 3, out + 16 * 3, key); + sms4_encrypt(in + 16 * 4, out + 16 * 4, key); + sms4_encrypt(in + 16 * 5, out + 16 * 5, key); + sms4_encrypt(in + 16 * 6, out + 16 * 6, key); + sms4_encrypt(in + 16 * 7, out + 16 * 7, key); +} + +void sms4_encrypt_16blocks(const unsigned char *in, unsigned char *out, const sms4_key_t *key) +{ + sms4_encrypt_8blocks(in, out, key); + sms4_encrypt_8blocks(in + 16 * 8, out + 16 * 8, key); +} diff --git a/crypto/sms4/sms4_lcl.h b/crypto/sms4/sms4_lcl.h new file mode 100644 index 00000000..4a06b893 --- /dev/null +++ b/crypto/sms4/sms4_lcl.h @@ -0,0 +1,122 @@ +/* ==================================================================== + * Copyright (c) 2014 - 2017 The GmSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the GmSSL Project. + * (http://gmssl.org/)" + * + * 4. The name "GmSSL Project" must not be used to endorse or promote + * products derived from this software without prior written + * permission. For written permission, please contact + * guanzhi1980@gmail.com. + * + * 5. Products derived from this software may not be called "GmSSL" + * nor may "GmSSL" appear in their names without prior written + * permission of the GmSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the GmSSL Project + * (http://gmssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE GmSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE GmSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ + +#ifndef HEADER_SMS4_LCL_H +#define HEADER_SMS4_LCL_H + +#ifdef __cplusplus +extern "C" { +#endif + +extern uint8_t SBOX[256]; +extern uint32_t SBOX32L[256 * 256]; +extern uint32_t SBOX32H[256 * 256]; + + +#define GET32(pc) ( \ + ((uint32_t)(pc)[0] << 24) ^ \ + ((uint32_t)(pc)[1] << 16) ^ \ + ((uint32_t)(pc)[2] << 8) ^ \ + ((uint32_t)(pc)[3])) + +#define PUT32(st, ct) \ + (ct)[0] = (uint8_t)((st) >> 24); \ + (ct)[1] = (uint8_t)((st) >> 16); \ + (ct)[2] = (uint8_t)((st) >> 8); \ + (ct)[3] = (uint8_t)(st) + +#define ROT32(x,i) \ + (((x) << i) | ((x) >> (32-i))) + +#define S32(A) \ + ((SBOX[((A) >> 24) ] << 24) ^ \ + (SBOX[((A) >> 16) & 0xff] << 16) ^ \ + (SBOX[((A) >> 8) & 0xff] << 8) ^ \ + (SBOX[((A)) & 0xff])) + +#define ROUNDS(x0, x1, x2, x3, x4) \ + ROUND(x0, x1, x2, x3, x4, 0); \ + ROUND(x1, x2, x3, x4, x0, 1); \ + ROUND(x2, x3, x4, x0, x1, 2); \ + ROUND(x3, x4, x0, x1, x2, 3); \ + ROUND(x4, x0, x1, x2, x3, 4); \ + ROUND(x0, x1, x2, x3, x4, 5); \ + ROUND(x1, x2, x3, x4, x0, 6); \ + ROUND(x2, x3, x4, x0, x1, 7); \ + ROUND(x3, x4, x0, x1, x2, 8); \ + ROUND(x4, x0, x1, x2, x3, 9); \ + ROUND(x0, x1, x2, x3, x4, 10); \ + ROUND(x1, x2, x3, x4, x0, 11); \ + ROUND(x2, x3, x4, x0, x1, 12); \ + ROUND(x3, x4, x0, x1, x2, 13); \ + ROUND(x4, x0, x1, x2, x3, 14); \ + ROUND(x0, x1, x2, x3, x4, 15); \ + ROUND(x1, x2, x3, x4, x0, 16); \ + ROUND(x2, x3, x4, x0, x1, 17); \ + ROUND(x3, x4, x0, x1, x2, 18); \ + ROUND(x4, x0, x1, x2, x3, 19); \ + ROUND(x0, x1, x2, x3, x4, 20); \ + ROUND(x1, x2, x3, x4, x0, 21); \ + ROUND(x2, x3, x4, x0, x1, 22); \ + ROUND(x3, x4, x0, x1, x2, 23); \ + ROUND(x4, x0, x1, x2, x3, 24); \ + ROUND(x0, x1, x2, x3, x4, 25); \ + ROUND(x1, x2, x3, x4, x0, 26); \ + ROUND(x2, x3, x4, x0, x1, 27); \ + ROUND(x3, x4, x0, x1, x2, 28); \ + ROUND(x4, x0, x1, x2, x3, 29); \ + ROUND(x0, x1, x2, x3, x4, 30); \ + ROUND(x1, x2, x3, x4, x0, 31) + +void sms4_init_sbox32(void); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/crypto/sms4/sms4_ofb.c b/crypto/sms4/sms4_ofb.c new file mode 100644 index 00000000..408d0b5a --- /dev/null +++ b/crypto/sms4/sms4_ofb.c @@ -0,0 +1,58 @@ +/* ==================================================================== + * Copyright (c) 2014 - 2017 The GmSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the GmSSL Project. + * (http://gmssl.org/)" + * + * 4. The name "GmSSL Project" must not be used to endorse or promote + * products derived from this software without prior written + * permission. For written permission, please contact + * guanzhi1980@gmail.com. + * + * 5. Products derived from this software may not be called "GmSSL" + * nor may "GmSSL" appear in their names without prior written + * permission of the GmSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the GmSSL Project + * (http://gmssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE GmSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE GmSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ + +#include +#include + + +void sms4_ofb128_encrypt(const unsigned char *in, unsigned char *out, + size_t len, const sms4_key_t *key, unsigned char *iv, int *num) +{ + CRYPTO_ofb128_encrypt(in, out, len, key, iv, num, (block128_f)sms4_encrypt); +} diff --git a/crypto/sms4/sms4_setkey.c b/crypto/sms4/sms4_setkey.c new file mode 100644 index 00000000..f5266424 --- /dev/null +++ b/crypto/sms4/sms4_setkey.c @@ -0,0 +1,116 @@ +/* ==================================================================== + * Copyright (c) 2014 - 2017 The GmSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the GmSSL Project. + * (http://gmssl.org/)" + * + * 4. The name "GmSSL Project" must not be used to endorse or promote + * products derived from this software without prior written + * permission. For written permission, please contact + * guanzhi1980@gmail.com. + * + * 5. Products derived from this software may not be called "GmSSL" + * nor may "GmSSL" appear in their names without prior written + * permission of the GmSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the GmSSL Project + * (http://gmssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE GmSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE GmSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ + +#include +#include "sms4_lcl.h" + +static uint32_t FK[4] = { + 0xa3b1bac6, 0x56aa3350, 0x677d9197, 0xb27022dc, +}; + +static uint32_t CK[32] = { + 0x00070e15, 0x1c232a31, 0x383f464d, 0x545b6269, + 0x70777e85, 0x8c939aa1, 0xa8afb6bd, 0xc4cbd2d9, + 0xe0e7eef5, 0xfc030a11, 0x181f262d, 0x343b4249, + 0x50575e65, 0x6c737a81, 0x888f969d, 0xa4abb2b9, + 0xc0c7ced5, 0xdce3eaf1, 0xf8ff060d, 0x141b2229, + 0x30373e45, 0x4c535a61, 0x686f767d, 0x848b9299, + 0xa0a7aeb5, 0xbcc3cad1, 0xd8dfe6ed, 0xf4fb0209, + 0x10171e25, 0x2c333a41, 0x484f565d, 0x646b7279, +}; + +#define L32_(x) \ + ((x) ^ \ + ROT32((x), 13) ^ \ + ROT32((x), 23)) + +#define ENC_ROUND(x0, x1, x2, x3, x4, i) \ + x4 = x1 ^ x2 ^ x3 ^ *(CK + i); \ + x4 = S32(x4); \ + x4 = x0 ^ L32_(x4); \ + *(rk + i) = x4 + +#define DEC_ROUND(x0, x1, x2, x3, x4, i) \ + x4 = x1 ^ x2 ^ x3 ^ *(CK + i); \ + x4 = S32(x4); \ + x4 = x0 ^ L32_(x4); \ + *(rk + 31 - i) = x4 + +void sms4_set_encrypt_key(sms4_key_t *key, const unsigned char *user_key) +{ + uint32_t *rk = key->rk; + uint32_t x0, x1, x2, x3, x4; + + x0 = GET32(user_key ) ^ FK[0]; + x1 = GET32(user_key + 4) ^ FK[1]; + x2 = GET32(user_key + 8) ^ FK[2]; + x3 = GET32(user_key + 12) ^ FK[3]; + +#define ROUND ENC_ROUND + ROUNDS(x0, x1, x2, x3, x4); + + x0 = x1 = x2 = x3 = x4 = 0; +} + +void sms4_set_decrypt_key(sms4_key_t *key, const unsigned char *user_key) +{ + uint32_t *rk = key->rk; + uint32_t x0, x1, x2, x3, x4; + + x0 = GET32(user_key ) ^ FK[0]; + x1 = GET32(user_key + 4) ^ FK[1]; + x2 = GET32(user_key + 8) ^ FK[2]; + x3 = GET32(user_key + 12) ^ FK[3]; + +#undef ROUND +#define ROUND DEC_ROUND + ROUNDS(x0, x1, x2, x3, x4); + + x0 = x1 = x2 = x3 = x4 = 0; +} diff --git a/crypto/sms4/sms4_wrap.c b/crypto/sms4/sms4_wrap.c new file mode 100644 index 00000000..95233a57 --- /dev/null +++ b/crypto/sms4/sms4_wrap.c @@ -0,0 +1,64 @@ +/* ==================================================================== + * Copyright (c) 2014 - 2017 The GmSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the GmSSL Project. + * (http://gmssl.org/)" + * + * 4. The name "GmSSL Project" must not be used to endorse or promote + * products derived from this software without prior written + * permission. For written permission, please contact + * guanzhi1980@gmail.com. + * + * 5. Products derived from this software may not be called "GmSSL" + * nor may "GmSSL" appear in their names without prior written + * permission of the GmSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the GmSSL Project + * (http://gmssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE GmSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE GmSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ + +#include +#include + + +int sms4_wrap_key(sms4_key_t *key, const unsigned char *iv, + unsigned char *out, const unsigned char *in, unsigned int inlen) +{ + return CRYPTO_128_wrap(key, iv, out, in, inlen, (block128_f)sms4_encrypt); +} + +int sms4_unwrap_key(sms4_key_t *key, const unsigned char *iv, + unsigned char *out, const unsigned char *in, unsigned int inlen) +{ + return CRYPTO_128_unwrap(key, iv, out, in, inlen, (block128_f)sms4_encrypt); +} diff --git a/crypto/sms4/sms4speed.c b/crypto/sms4/sms4speed.c new file mode 100644 index 00000000..f5793d2f --- /dev/null +++ b/crypto/sms4/sms4speed.c @@ -0,0 +1,86 @@ +/* ==================================================================== + * Copyright (c) 2014 - 2017 The GmSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the GmSSL Project. + * (http://gmssl.org/)" + * + * 4. The name "GmSSL Project" must not be used to endorse or promote + * products derived from this software without prior written + * permission. For written permission, please contact + * guanzhi1980@gmail.com. + * + * 5. Products derived from this software may not be called "GmSSL" + * nor may "GmSSL" appear in their names without prior written + * permission of the GmSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the GmSSL Project + * (http://gmssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE GmSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE GmSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ + + +#include +#include +#include +#include +#include +#include + + +int main(int argc, char **argv) +{ + sms4_key_t sms4_key; + unsigned char user_key[16] = { + 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, + 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, + }; + size_t buflen = SMS4_BLOCK_SIZE * 8 * 3 * 1000 * 1000; + unsigned char *buf = NULL; + unsigned char *p; + int i; + + + if (!(buf = (unsigned char *)malloc(buflen))) { + fprintf(stderr, "malloc failed\n"); + return -1; + } + + sms4_set_encrypt_key(&sms4_key, user_key); + + #pragma omp parallel for + for (i = 0, p = buf; i < buflen/(SMS4_BLOCK_SIZE * 16); i++, p += SMS4_BLOCK_SIZE * 16) { + sms4_encrypt_16blocks(&sms4_key, p, p); + } + + return 0; +} + diff --git a/include/openssl/evp.h b/include/openssl/evp.h index 6f042433..21ccee9a 100644 --- a/include/openssl/evp.h +++ b/include/openssl/evp.h @@ -889,6 +889,27 @@ const EVP_CIPHER *EVP_seed_cfb128(void); const EVP_CIPHER *EVP_seed_ofb(void); # endif +# ifndef OPENSSL_NO_SMS4 +const EVP_CIPHER *EVP_sms4_ecb(void); +const EVP_CIPHER *EVP_sms4_cbc(void); +const EVP_CIPHER *EVP_sms4_cfb1(void); +const EVP_CIPHER *EVP_sms4_cfb8(void); +const EVP_CIPHER *EVP_sms4_cfb128(void); +# define EVP_sms4_cfb EVP_sms4_cfb128 +const EVP_CIPHER *EVP_sms4_ofb(void); +const EVP_CIPHER *EVP_sms4_ctr(void); +const EVP_CIPHER *EVP_sms4_gcm(void); +const EVP_CIPHER *EVP_sms4_ccm(void); +const EVP_CIPHER *EVP_sms4_ocb(void); +const EVP_CIPHER *EVP_sms4_xts(void); +const EVP_CIPHER *EVP_sms4_wrap(void); +const EVP_CIPHER *EVP_sms4_wrap_pad(void); +# define EVP_sm4_ecb EVP_sms4_ecb +# define EVP_sm4_cbc EVP_sms4_cbc +# define EVP_sm4_cfb EVP_sms4_cfb +# define EVP_sm4_ofb EVP_sms4_ofb +# endif + # if OPENSSL_API_COMPAT < 0x10100000L # define OPENSSL_add_all_algorithms_conf() \ OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS \ diff --git a/include/openssl/sms4.h b/include/openssl/sms4.h new file mode 100644 index 00000000..cb216fb1 --- /dev/null +++ b/include/openssl/sms4.h @@ -0,0 +1,123 @@ +/* ==================================================================== + * Copyright (c) 2014 - 2017 The GmSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the GmSSL Project. + * (http://gmssl.org/)" + * + * 4. The name "GmSSL Project" must not be used to endorse or promote + * products derived from this software without prior written + * permission. For written permission, please contact + * guanzhi1980@gmail.com. + * + * 5. Products derived from this software may not be called "GmSSL" + * nor may "GmSSL" appear in their names without prior written + * permission of the GmSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the GmSSL Project + * (http://gmssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE GmSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE GmSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ + +#ifndef HEADER_SMS4_H +#define HEADER_SMS4_H + +#include +#ifndef NO_GMSSL + +#define SMS4_KEY_LENGTH 16 +#define SMS4_BLOCK_SIZE 16 +#define SMS4_IV_LENGTH (SMS4_BLOCK_SIZE) +#define SMS4_NUM_ROUNDS 32 + +#include +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + uint32_t rk[SMS4_NUM_ROUNDS]; +} sms4_key_t; + +void sms4_set_encrypt_key(sms4_key_t *key, const unsigned char *user_key); +void sms4_set_decrypt_key(sms4_key_t *key, const unsigned char *user_key); +void sms4_encrypt(const unsigned char *in, unsigned char *out, const sms4_key_t *key); +#define sms4_decrypt(in,out,key) sms4_encrypt(in,out,key) + +void sms4_encrypt_init(sms4_key_t *key); +void sms4_encrypt_8blocks(const unsigned char *in, unsigned char *out, const sms4_key_t *key); +void sms4_encrypt_16blocks(const unsigned char *in, unsigned char *out, const sms4_key_t *key); + +void sms4_ecb_encrypt(const unsigned char *in, unsigned char *out, + const sms4_key_t *key, int enc); +void sms4_cbc_encrypt(const unsigned char *in, unsigned char *out, + size_t len, const sms4_key_t *key, unsigned char *iv, int enc); +void sms4_cfb128_encrypt(const unsigned char *in, unsigned char *out, + size_t len, const sms4_key_t *key, unsigned char *iv, int *num, int enc); +void sms4_ofb128_encrypt(const unsigned char *in, unsigned char *out, + size_t len, const sms4_key_t *key, unsigned char *iv, int *num); +void sms4_ctr128_encrypt(const unsigned char *in, unsigned char *out, + size_t len, const sms4_key_t *key, unsigned char *iv, + unsigned char ecount_buf[SMS4_BLOCK_SIZE], unsigned int *num); + +int sms4_wrap_key(sms4_key_t *key, const unsigned char *iv, + unsigned char *out, const unsigned char *in, unsigned int inlen); +int sms4_unwrap_key(sms4_key_t *key, const unsigned char *iv, + unsigned char *out, const unsigned char *in, unsigned int inlen); + + + +#define SMS4_EDE_KEY_LENGTH 32 + +typedef struct { + sms4_key_t k1; + sms4_key_t k2; +} sms4_ede_key_t; + +void sms4_ede_set_encrypt_key(sms4_ede_key_t *key, const unsigned char *user_key); +void sms4_ede_set_decrypt_key(sms4_ede_key_t *key, const unsigned char *user_key); +void sms4_ede_encrypt(sms4_ede_key_t *key, const unsigned char *in, unsigned char *out); +void sms4_ede_encrypt_8blocks(sms4_ede_key_t *key, const unsigned char *in, unsigned char *out); +void sms4_ede_encrypt_16blocks(sms4_ede_key_t *key, const unsigned char *in, unsigned char *out); +void sms4_ede_decrypt(sms4_ede_key_t *key, const unsigned char *in, unsigned char *out); +void sms4_ede_decrypt_8blocks(sms4_ede_key_t *key, const unsigned char *in, unsigned char *out); +void sms4_ede_decrypt_16blocks(sms4_ede_key_t *key, const unsigned char *in, unsigned char *out); + + +#ifdef __cplusplus +} +#endif +#endif +#endif diff --git a/test/build.info b/test/build.info index 2ed6dc12..b7163505 100644 --- a/test/build.info +++ b/test/build.info @@ -17,7 +17,7 @@ IF[{- !$disabled{tests} -}] dtlsv1listentest ct_test threadstest afalgtest d2i_test \ ssl_test_ctx_test ssl_test x509aux cipherlist_test asynciotest \ bioprinttest sslapitest dtlstest sslcorrupttest bio_enc_test \ - sm3test + sm3test sms4test SOURCE[aborttest]=aborttest.c INCLUDE[aborttest]=../include @@ -288,6 +288,10 @@ IF[{- !$disabled{tests} -}] INCLUDE[sm3test]=../include DEPEND[sm3test]=../libcrypto + SOURCE[sms4test]=sms4test.c + INCLUDE[sms4test]=../include + DEPEND[sms4test]=../libcrypto + IF[{- !$disabled{shared} -}] PROGRAMS_NO_INST=shlibloadtest SOURCE[shlibloadtest]=shlibloadtest.c diff --git a/test/recipes/05-test_sms4.t b/test/recipes/05-test_sms4.t new file mode 100644 index 00000000..12c584f5 --- /dev/null +++ b/test/recipes/05-test_sms4.t @@ -0,0 +1,12 @@ +#! /usr/bin/env perl +# Copyright 2015-2016 The OpenSSL Project Authors. All Rights Reserved. +# +# Licensed under the OpenSSL license (the "License"). You may not use +# this file except in compliance with the License. You can obtain a copy +# in the file LICENSE in the source distribution or at +# https://www.openssl.org/source/license.html + + +use OpenSSL::Test::Simple; + +simple_test("test_sms4", "sms4test", "sms4"); diff --git a/test/recipes/70-test_sslcbcpadding.t b/test/recipes/70-test_sslcbcpadding.t index fdaa4668..890f9cf0 100644 --- a/test/recipes/70-test_sslcbcpadding.t +++ b/test/recipes/70-test_sslcbcpadding.t @@ -29,7 +29,7 @@ plan skip_all => "$test_name needs TLSv1.2 enabled" $ENV{OPENSSL_ia32cap} = '~0x200000200000000'; my $proxy = TLSProxy::Proxy->new( \&add_maximal_padding_filter, - cmdstr(app(["openssl"]), display => 1), + cmdstr(app(["gmssl"]), display => 1), srctop_file("apps", "server.pem"), (!$ENV{HARNESS_ACTIVE} || $ENV{HARNESS_VERBOSE}) ); diff --git a/test/recipes/70-test_sslcertstatus.t b/test/recipes/70-test_sslcertstatus.t index f700f928..43ee5c46 100755 --- a/test/recipes/70-test_sslcertstatus.t +++ b/test/recipes/70-test_sslcertstatus.t @@ -32,7 +32,7 @@ plan skip_all => "$test_name needs TLS enabled" $ENV{OPENSSL_ia32cap} = '~0x200000200000000'; my $proxy = TLSProxy::Proxy->new( \&certstatus_filter, - cmdstr(app(["openssl"]), display => 1), + cmdstr(app(["gmssl"]), display => 1), srctop_file("apps", "server.pem"), (!$ENV{HARNESS_ACTIVE} || $ENV{HARNESS_VERBOSE}) ); diff --git a/test/recipes/70-test_sslextension.t b/test/recipes/70-test_sslextension.t index 7f69f649..bc21d537 100755 --- a/test/recipes/70-test_sslextension.t +++ b/test/recipes/70-test_sslextension.t @@ -29,7 +29,7 @@ plan skip_all => "$test_name needs TLS enabled" $ENV{OPENSSL_ia32cap} = '~0x200000200000000'; my $proxy = TLSProxy::Proxy->new( \&extension_filter, - cmdstr(app(["openssl"]), display => 1), + cmdstr(app(["gmssl"]), display => 1), srctop_file("apps", "server.pem"), (!$ENV{HARNESS_ACTIVE} || $ENV{HARNESS_VERBOSE}) ); diff --git a/test/sms4test.c b/test/sms4test.c new file mode 100644 index 00000000..8d364454 --- /dev/null +++ b/test/sms4test.c @@ -0,0 +1,139 @@ +/* ==================================================================== + * Copyright (c) 2014 - 2017 The GmSSL Project. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the GmSSL Project. + * (http://gmssl.org/)" + * + * 4. The name "GmSSL Project" must not be used to endorse or promote + * products derived from this software without prior written + * permission. For written permission, please contact + * guanzhi1980@gmail.com. + * + * 5. Products derived from this software may not be called "GmSSL" + * nor may "GmSSL" appear in their names without prior written + * permission of the GmSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the GmSSL Project + * (http://gmssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE GmSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE GmSSL PROJECT OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + */ + +#include +#include +#include +#include "../e_os.h" + +#ifdef OPENSSL_NO_SMS4 +int main(int argc, char **argv) +{ + printf("NO SMS4 support\n"); + return 0; +} +#else +# include +# include + +int main(int argc, char **argv) +{ + int err = 0; + int i; + sms4_key_t key; + unsigned char buf[16]; + + unsigned char user_key[16] = { + 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, + }; + + uint32_t rk[32] = { + 0xf12186f9, 0x41662b61, 0x5a6ab19a, 0x7ba92077, + 0x367360f4, 0x776a0c61, 0xb6bb89b3, 0x24763151, + 0xa520307c, 0xb7584dbd, 0xc30753ed, 0x7ee55b57, + 0x6988608c, 0x30d895b7, 0x44ba14af, 0x104495a1, + 0xd120b428, 0x73b55fa3, 0xcc874966, 0x92244439, + 0xe89e641f, 0x98ca015a, 0xc7159060, 0x99e1fd2e, + 0xb79bd80c, 0x1d2115b0, 0x0e228aeb, 0xf1780c81, + 0x428d3654, 0x62293496, 0x01cf72e5, 0x9124a012, + }; + + unsigned char plaintext[16] = { + 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, + }; + + unsigned char ciphertext1[16] = { + 0x68, 0x1e, 0xdf, 0x34, 0xd2, 0x06, 0x96, 0x5e, + 0x86, 0xb3, 0xe9, 0x4f, 0x53, 0x6e, 0x42, 0x46, + }; + + unsigned char ciphertext2[16] = { + 0x59, 0x52, 0x98, 0xc7, 0xc6, 0xfd, 0x27, 0x1f, + 0x04, 0x02, 0xf8, 0x04, 0xc3, 0x3d, 0x3f, 0x66, + }; + + /* test key scheduling */ + sms4_set_encrypt_key(&key, user_key); + + if (memcmp(key.rk, rk, sizeof(rk)) != 0) { + printf("sms4 key scheduling not passed!\n"); + goto end; + } + printf("sms4 key scheduling passed!\n"); + + /* test encrypt once */ + sms4_encrypt(plaintext, buf, &key); + + if (memcmp(buf, ciphertext1, sizeof(ciphertext1)) != 0) { + printf("sms4 encrypt not pass!\n"); + goto end; + } + printf("sms4 encrypt pass!\n"); + + /* test encrypt 1000000 times */ + memcpy(buf, plaintext, sizeof(plaintext)); + for (i = 0; i < 1000000; i++) { + sms4_encrypt(buf, buf, &key); + } + + if (memcmp(buf, ciphertext2, sizeof(ciphertext2)) != 0) { + printf("sms4 encrypt 1000000 times not pass!\n"); + goto end; + } + printf("sms4 encrypt 1000000 times pass!\n"); + printf("sms4 all test vectors pass!\n"); + + return err; +end: + printf("some test vector failed\n"); + return -1; +} +#endif diff --git a/util/libcrypto.num b/util/libcrypto.num index 409f6305..23352ab6 100644 --- a/util/libcrypto.num +++ b/util/libcrypto.num @@ -4215,3 +4215,16 @@ X509_VERIFY_PARAM_get_inh_flags 4175 1_1_0d EXIST::FUNCTION: X509_VERIFY_PARAM_get_time 4181 1_1_0d EXIST::FUNCTION: DH_check_params 4183 1_1_0d EXIST::FUNCTION:DH EVP_sm3 4184 1_1_0d EXIST::FUNCTION: +EVP_sms4_xts 4185 1_1_0d EXIST::FUNCTION: +EVP_sms4_wrap 4186 1_1_0d EXIST::FUNCTION: +EVP_sms4_ecb 4187 1_1_0d EXIST::FUNCTION: +EVP_sms4_cfb128 4188 1_1_0d EXIST::FUNCTION: +EVP_sms4_cfb1 4189 1_1_0d EXIST::FUNCTION: +EVP_sms4_cbc 4190 1_1_0d EXIST::FUNCTION: +EVP_sms4_ofb 4191 1_1_0d EXIST::FUNCTION: +EVP_sms4_ctr 4192 1_1_0d EXIST::FUNCTION: +EVP_sms4_cfb8 4193 1_1_0d EXIST::FUNCTION: +EVP_sms4_gcm 4194 1_1_0d EXIST::FUNCTION: +EVP_sms4_ocb 4195 1_1_0d EXIST::FUNCTION: +EVP_sms4_ccm 4196 1_1_0d EXIST::FUNCTION: +EVP_sms4_wrap_pad 4197 1_1_0d EXIST::FUNCTION: