Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

An implementation of the Chinese SM4 block cipher #4552

Closed
wants to merge 9 commits into from

Conversation

ronaldtse
Copy link
Contributor

@ronaldtse ronaldtse commented Oct 18, 2017

This PR introduces the Chinese SM4 algorithm which is a 128-bit block cipher.

It was originally ported from Ribose's contribution to Botan, but has received further updates to make its performance on par with the SM4 implementation there.

Currently openssl speed -evp sm4-ecb reports:

This is a contribution by Ribose Inc. and was done with knowledge of @richsalz, @levitte, @InfoHunter.

There might be some stuff missing but please do bring on the review process 😉 .

cc: @randombit @dewyatt @erikbor

This is a contribution from Ribose Inc..

Checklist
  • documentation is added or updated
  • tests are added or updated

@openssl-machine openssl-machine added the hold: cla required The contributor needs to submit a license agreement label Oct 18, 2017
@mattcaswell
Copy link
Member

The CLA bot is complaining because the commit author in two of the commits is given as "Jack Lloyd" with an email address that is not in our CLA database.

@ronaldtse
Copy link
Contributor Author

Thank you @mattcaswell for letting us know, we'll fix that.

@openssl-machine openssl-machine added the hold: cla required The contributor needs to submit a license agreement label Oct 18, 2017
@ronaldtse
Copy link
Contributor Author

Some more things to fix:

crypto/sm4/sm4.c: In function 'SM4_T_slow':
crypto/sm4/sm4.c:117:5: error: C++ style comments are not allowed in ISO C90 [-Werror]
     // L linear transform
     ^
crypto/sm4/sm4.c:117:5: error: (this will be reported only once per input file) [-Werror]
crypto/sm4/sm4.c: In function 'SM4_set_key':
crypto/sm4/sm4.c:153:5: error: ISO C90 forbids mixed declarations and code [-Werror=pedantic]
     uint8_t i;
     ^

@ronaldtse
Copy link
Contributor Author

One more:

�[0K$ if $make update; then echo -e '+\057 MAKE UPDATE OK'; else echo -e '+\057 MAKE UPDATE FAILED'; false; fi; git diff --quiet
LIBCRYPTO: 3 old symbols have updated info
LIBCRYPTO: No new symbols added
LIBSSL: No new symbols added
+/ MAKE UPDATE OK

travis_time:end:2e8b5d1f:start=1508350360675991669,finish=1508350365743647727,duration=5067656058
�[0K
�[31;1mThe command "if $make update; then echo -e '+/ MAKE UPDATE OK'; else echo -e '+/ MAKE UPDATE FAILED'; false; fi; git diff --quiet" exited with 1.�[0m

Copy link
Member

@mattcaswell mattcaswell left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This code looks very neat. I just have a few (mostly style) comments. I've not verified the implementation against the spec (where is the spec?).

const SM4_KEY * key, const int enc)
{
if (enc)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove this stray blank line

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed.


void SM4_encrypt(const uint8_t *in, uint8_t *out, const SM4_KEY * ks);

void SM4_decrypt(const uint8_t *in, uint8_t *out, const SM4_KEY * ks);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No space between '*' and ks, i.e. it should be const SM4_KEY *ks

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed.

crypto/sm4/sm4.c Outdated

static inline uint32_t SM4_T_slow(uint32_t X)
{
uint32_t t = 0;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Blank line after declaration

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed.

crypto/sm4/sm4.c Outdated
for (i = 0; i != 32; ++i) {
uint32_t X = K[(i + 1) % 4] ^ K[(i + 2) % 4] ^ K[(i + 3) % 4] ^ CK[i];

uint32_t t = 0;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No blank line above here - should be one below it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed.

crypto/sm4/sm4.c Outdated
K[2] = load_u32_be(key, 2) ^ FK[2];
K[3] = load_u32_be(key, 3) ^ FK[3];

for (i = 0; i != 32; ++i) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably should be SM4_KEY_SCHEDULE instead of 32?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed.

crypto/sm4/sm4.c Outdated
return 1;
}

#define SM4_RNDS(k0,k1,k2,k3,F) do { \
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Leave a space after each ,

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed.

@@ -2078,6 +2078,36 @@ Operation = ENCRYPT
Plaintext = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F20212223
Ciphertext = A4DA23FCE6A5FFAA6D64AE9A0652A42CD161A34B65F9679F75C01F101F71276F15EF0D8D

Title = SM4 test vectors
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the origin of these test vectors? Can we include a reference?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Included a reference to IETF draft-ribose-cfrg-sm4.

test/sm4test.c Outdated
SM4_KEY key;
SM4_set_key(k, &key);

uint8_t block[16];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't use SM4_BLOCK_SIZE here - but perhaps a define instead of a magic number here (and other instances below) would be better?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, since internal/sm4.h is included, it's perfectly possible to use SM4_BLOCK_SIZE...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using SM4_BLOCK_SIZE now, moved to test/sm4_internal_test.c.

EVP_sm4_cbc 4369 1_1_1 EXIST::FUNCTION:SM4
EVP_sm4_ofb 4370 1_1_1 EXIST::FUNCTION:SM4
EVP_sm4_cfb128 4371 1_1_1 EXIST::FUNCTION:SM4
EVP_sm4_ctr 4372 1_1_1 EXIST::FUNCTION:SM4
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suggest you remove these changes and do a make update again. You'll find that the SM4_* symbols will not appear... (that's the update of 3 symbols that's mentioned in Travis, make update wants to change their state to NOEXIST)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@levitte I've done this. Somehow make update on my machine adds a last line of license ... EXIST::FUNCTION to the end, which I've removed manually... Let me know if this behavior is correct.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have no idea why it adds a license line... It shouldn't, and it doesn't for me...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @levitte for the confirmation 👍

@paulidale
Copy link
Contributor

When I looked at these a while back, the best English reference I could locate for SM4 / SMS4 is: SMS4 Encryption Algorithm for Wireless Networks. There is a much better IETF draft now. There is of course a Chinese specification but I'm unable to read it.

The question in my mind is should the Chinese cryptographic primitives be wrapped in an engine like GOST is?

SM4 is but one of several defined algorithms, SM2 and SM3 are also IETF drafts, albeit expired ones. I also found a reference describing SM9. I've not looked for a ZUC definition. There are more algorithms than this.

@openssl-machine openssl-machine added the hold: cla required The contributor needs to submit a license agreement label Oct 19, 2017
@ronaldtse
Copy link
Contributor Author

@paulidale the Internet-Draft for SM4 is intended to fully cover the official standard GB/T 32907-2016 (in Sections 1 to 7), as well as modes of operation and some considerations that were not covered by the standard.

SMS4 Encryption Algorithm for Wireless Networks is a translation based on an older standard published by OSCCA called GM/T 0002-2012, which is not currently available on the Internet.

@openssl-machine openssl-machine added the hold: cla required The contributor needs to submit a license agreement label Oct 19, 2017
0x86, 0xb3, 0xe9, 0x4f, 0x53, 0x6e, 0x42, 0x46
};

// after 1,000,000 iterations
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Change that to a classic C comment, please

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed.


use OpenSSL::Test::Simple;

simple_test("test_internal_sm4", "sm4_internal_test", "sm4");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please rename this file to go along with the other internal tests. 03-test_internal_sm4.t would be a good one.

Also, since this is only built under certain condicions, you need to add the following as well, before the simple_test line:

plan skip_all => "This test is unsupported in a shared library build on Windows"
    if $^O eq 'MSWin32' && !disabled("shared");

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done, thanks @levitte !

@openssl-machine openssl-machine added the hold: cla required The contributor needs to submit a license agreement label Oct 19, 2017
@@ -0,0 +1,103 @@
/*
* Copyright 2017 The OpenSSL Project Authors. All Rights Reserved.
* Copyright 2017 [Ribose Inc.](https://www.ribose.com). All Rights Reserved.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As I saw in other files, seems the copyright line should contain company name without the URL (correct me if I am wrong), the []() likes a markdown syntax...

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems odd to me too. Better would be:

Copyright 2017 Ribose Inc. All Rights Reserved.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed.

sm4_cfb128 1137
sm4_cfb8 1138
sm4_ctr 1139
ISO_CN 1140
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should the number be aligned to others? Or the 2-tabs is fixed there?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file is generated, so...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will feel challenged to make the generation script properly align 😉

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Haha

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ahh...

crypto/sm4/sm4.c Outdated
};

/*
* SM4_SBOX_T[j] == L(SM4_SBOX[j]).
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indentation. And I think this could be placed in one line as /* */...

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indentation addressed.

crypto/sm4/sm4.c Outdated
* SM4_SBOX_T[j] == L(SM4_SBOX[j]).
*/
static const uint32_t SM4_SBOX_T[256] = {
0x8ED55B5B, 0xD0924242, 0x4DEAA7A7, 0x06FDFBFB, 0xFCCF3333, 0x65E28787,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

4 spaces indent...

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed.

@@ -0,0 +1,19 @@
#! /usr/bin/env perl
# Copyright 2015-2016 The OpenSSL Project Authors. All Rights Reserved.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copyright 2017 The OpenSSL...?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed.

static int test_sm4_ecb(void)
{
static const uint8_t k[SM4_BLOCK_SIZE] = {
0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indent should be 4-spaces, so do the followings...

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed.

crypto/sm4/sm4.c Outdated
return 1;
}

#define SM4_RNDS(k0, k1, k2, k3, F) do { \
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess it's preferred if the do statement is placed in next line as:

    #define macrofun(a, b, c)   \
        do {                    \
            if (a == 5)         \
                do_this(b, c);  \
        } while (0)

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed.

@InfoHunter
Copy link
Member

And documentation is missing...

@levitte
Copy link
Member

levitte commented Oct 19, 2017

And documentation is missing...

@InfoHunter is right. There should be a new entry in the CIPHER LISTING section in doc/man3/EVP_EncryptInit.pod.

@paulidale
Copy link
Contributor

@ronaldtse thanks for the better links.

@openssl-machine openssl-machine added the hold: cla required The contributor needs to submit a license agreement label Oct 20, 2017
@ronaldtse
Copy link
Contributor Author

@InfoHunter @levitte added new section in CIPHER LISTING. I noticed that some of the ciphers are actually missing in doc/man3/EncryptInit.pod:

  • all the CTR modes: EVP_aes_{128,192,256}_ctr(), EVP_aria_{128,192,256}_ctr(), EVP_camellia_{128,192,256}_ctr()
  • all the aria ones: EVP_aria_{128,192,256}_{ecb,cbc,cfb,cfb1,cfb8,ctr,ofb,gcm,ccm}
  • all the camellia ones: EVP_camellia_{128,192,256}_{ecb,cbc,cfb,cfb1,cfb8,ctr,ofb,gcm,ccm}

Should these be added?

@kroeckx
Copy link
Member

kroeckx commented Oct 20, 2017

They should probably all get added, but I suggest you do that in a different pull request so that we can merge that to other branches.

crypto/sm4/sm4.c Outdated
0x794C3535, 0xA0208080, 0x9D78E5E5, 0x56EDBBBB, 0x235E7D7D, 0xC63EF8F8,
0x8BD45F5F, 0xE7C82F2F, 0xDD39E4E4, 0x68492121 };

static inline uint32_t rotl(uint32_t a, uint8_t n)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

inline is not portable, use ossl_inline.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @dot-asm ! Addressed.

@ronaldtse
Copy link
Contributor Author

One last rebase.

Copy link
Member

@levitte levitte left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup

@dot-asm
Copy link
Contributor

dot-asm commented Oct 30, 2017

OMC is looking at it [enabled vs. disabled by default] now.

It's obvious that there probably can't be a solid common criteria for deciding either way. Especially since there are contradicting cases when things look the way they do rather for backward compatibility sake than anything else. But it doesn't mean that one shouldn't attempt to formulate multiple criteria and consider combination. One of such criteria can [or should?] be public record of independent cryptanalysis... Another is ability to withstand side channel attacks... Recognized [non-proprietary] application...

@richsalz
Copy link
Contributor

Yes, @dot-asm, you're right. And also the ability of the project to maintain these things in the face of attacks. It's an interesting question.

@dot-asm
Copy link
Contributor

dot-asm commented Oct 30, 2017

BTW, siphash was previously mentioned. Note that it's not released, so one can still change that...

@paulidale
Copy link
Contributor

A rebase is required before merge :(

@paulidale
Copy link
Contributor

Another consideration is that enabling an algorithm wouldn't be considered API changing whereas disabling one would be. I.e. disabled by default is changeable in a minor release.

Jack Lloyd and others added 9 commits October 31, 2017 07:51
* remove for-loop initial declarations that are only allowed in C99
* update SM4 numbers in libcrypto.num via `make update`
* fix C90 issues
* style fixes as commented by mattcaswell
* remaining style fixes
* cleanup test vectors and add reference
* use SM4_KEY_SCHEDULE instead of 32
* cleanup comments
* include internal test, and use SM4_BLOCK_SIZE
* add documentation
* use ossl_inline for portability
* remove unnecessary includes
* no spaces after cast
* use (uint8_t) cast instead of `& 0xFF`
* use int in for loop
* use `or` in load_u32_be instead of `xor`
@ronaldtse
Copy link
Contributor Author

@paulidale rebased again!

@paulidale
Copy link
Contributor

Thanks, waiting for the Travis build to finish before merging.

levitte pushed a commit that referenced this pull request Oct 31, 2017
Reviewed-by: Richard Levitte <levitte@openssl.org>
Reviewed-by: Paul Dale <paul.dale@oracle.com>
(Merged from #4552)
@paulidale
Copy link
Contributor

Merged, thanks.

@paulidale paulidale closed this Oct 31, 2017
@ronaldtse
Copy link
Contributor Author

Thank you @paulidale and everyone here !

Copy link

@liuqun liuqun left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some trailing white spaces in crypto/objects/objects.txt were removed during this PR. Many text editors have such feature to remove all trailing white spaces, some of these white space changes are unrelated to the current PR.

Hope we can use some .c and .txt formatter to remove such unnecessary trailing white spaces before more new pull requests arrives.

util/openssl-format-source -v -c ignores crypto/objects/objects.txt, I guess.
See: https://github.com/openssl/openssl/blob/master/util/openssl-format-source

@@ -1368,7 +1368,7 @@ member-body 643 100 112 : issuerSignTool : Signing Tool of Issuer
# Definitions for Camellia cipher - ECB, CFB, OFB MODE

!Alias ntt-ds 0 3 4401 5
!Alias camellia ntt-ds 3 1 9
!Alias camellia ntt-ds 3 1 9
Copy link

@liuqun liuqun Apr 8, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

An unrelated white space change here.

@@ -1498,7 +1515,7 @@ ISO-US 10046 2 1 : dhpublicnumber : X9.42 DH
1 3 36 3 3 2 8 1 1 11 : brainpoolP384r1
1 3 36 3 3 2 8 1 1 12 : brainpoolP384t1
1 3 36 3 3 2 8 1 1 13 : brainpoolP512r1
1 3 36 3 3 2 8 1 1 14 : brainpoolP512t1
1 3 36 3 3 2 8 1 1 14 : brainpoolP512t1
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another unrelated white space change.

@InfoHunter
Copy link
Member

I don't think it was improper to remove these spaces here.

Long ago I learned the 'style' of this project which was: "if your changes are next to a nit, then you fix the nit incidentally' ;-)

@levitte
Copy link
Member

levitte commented Apr 9, 2018

Why these comments on a PR that was approved and merged a long time ago?

@ronaldtse
Copy link
Contributor Author

@levitte seems that it was due to increased interest given news of OpenSSL 1.1.1 now supports these algorithms 😉👏

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet