From 33edd27c2973a3e7b5ca7a51e978adb4f5578a81 Mon Sep 17 00:00:00 2001 From: Karel Miko Date: Sun, 19 Apr 2026 23:31:06 +0200 Subject: [PATCH 1/9] SM3 hash function --- doc/crypt.tex | 3 +- notes/hash_tv.txt | 131 +++++++ notes/hmac_tv.txt | 131 +++++++ src/hashes/sm3.c | 423 +++++++++++++++++++++ src/headers/tomcrypt_custom.h | 1 + src/headers/tomcrypt_hash.h | 19 + src/mac/hmac/hmac_test.c | 34 ++ src/misc/crypt/crypt.c | 3 + src/misc/crypt/crypt_register_all_hashes.c | 3 + tests/test.c | 3 + 10 files changed, 750 insertions(+), 1 deletion(-) create mode 100644 src/hashes/sm3.c diff --git a/doc/crypt.tex b/doc/crypt.tex index fc879fa9a..622e7ee12 100644 --- a/doc/crypt.tex +++ b/doc/crypt.tex @@ -2998,6 +2998,7 @@ \subsection{Hash Registration} \hline RIPEMD-256 & rmd160\_desc & 32 & 13 \\ \hline BLAKE2S-256 & blake2s\_256\_desc & 32 & 24 \\ \hline BLAKE2B-256 & blake2b\_256\_desc & 32 & 26 \\ + \hline SM3 & sm3\_desc & 32 & 34 \\ \hline SHA-512/224 & sha512\_224\_desc & 28 & 15 \\ \hline Keccak224 & keccak\_224\_desc & 28 & 29 \\ \hline SHA3-224 & sha3\_224\_desc & 28 & 17 \\ @@ -3224,7 +3225,7 @@ \subsection{KangarooTwelve} These hashes are provided for completeness and they still can be used for the purposes of password hashing or one-way accumulators (e.g. Yarrow). -The other hashes such as the SHA-2 (that includes SHA-512, SHA-512/384, SHA-384, SHA-512/256, SHA-256 and SHA-224), TIGER-192 and TIGER2-192 are still +The other hashes such as the SHA-2 (that includes SHA-512, SHA-512/384, SHA-384, SHA-512/256, SHA-256 and SHA-224), SM3, TIGER-192 and TIGER2-192 are still considered secure for all purposes you would normally use a hash for. \chapter{Checksum Functions} diff --git a/notes/hash_tv.txt b/notes/hash_tv.txt index c9f8e72a7..21c01fd5a 100644 --- a/notes/hash_tv.txt +++ b/notes/hash_tv.txt @@ -6053,6 +6053,137 @@ Hash: md4 127: 2067886DA4BDE10A94B971CD740B0AAB 128: E1275970EB67D2D996E6E658270AA149 +Hash: sm3 + 0: 1AB21D8355CFA17F8E61194831E81A8F22BEC8C728FEFB747ED035EB5082AA2B + 1: 2DAEF60E7A0B8F5E024C81CD2AB3109F2B4F155CF83ADEB2AE5532F74A157FDF + 2: D8AABBEF65E6196AE1106FDDF48CDD0FD6EEE7FF54CD678F209B4914426B0221 + 3: D18C17EF9F985BA361F06B599A1EC3CAE9BD5DE6967CAC33944E5F8B67B6DCC2 + 4: 4B41BC3558731767A4B19187A64F8D171878EF5A45BFD73670815C2C66387D75 + 5: 96EDA336EB22EE830F1D1354CE363872497171A3EAC3CDF1D251C88BD4D28D2F + 6: 728ED1FF1C9FF55249889985CB21187D6E4F9516CC5CDBA5F7CCE79F5FF12DF9 + 7: F4AFC6E2843C2B00DE925B36259E386659BB727CFC528016F434E2D79AE46E7B + 8: 6C79B88EE30D03CB22B842BFCC15A18F839F70EAADBD3BDA953C6AA31092F83B + 9: D9260EB16F78E835EAD5B02FCA32321439FAFFC1763507DF21B3848EEAD70E73 + 10: 24C898BDB4D258F9BEBB2E820D4ED478A7C013B37BD9E5006515730C18A70416 + 11: 25982ABCAF86A30979CFBD4F86C76F2A3160F916CA0301A55C1B48DB89C8D7C5 + 12: B1A7B180FFD9147FA043ACFE6C794E902656C502B4F241B01F9DE1229562205B + 13: 65721525FCA963BFB01D5250A032AD3FC15F5D3B1E591906E892F8ABD4499A5E + 14: 386D2B4DCB208DB57B938C345338BDBEC61547EED302ECD273992A64876155D7 + 15: C706E492B6994B610A4B62ABA68E797772AB5DC2764EC35980DBA24734CA2EB1 + 16: F65C16E869F79670DEE45F4B56FE2B3E0308D8FEFC3214E16C64B7F5D3741E89 + 17: 431F00611D6EDCBAEB4C53C8F94148478A894E34383984F6D3BC45D144EF1B1C + 18: FE4C9FF5DEF43DD8A6E1EED798AE1515871BAF70FDE50A7F9AA3391C53604FF3 + 19: 674ED992C21A2842673AF768EB51374790252097CA545F426AF6F898865BA903 + 20: 54001A49B4CD4275A032A257405FF7CB0CB8B396DD9D8D4D387F4A5840EE0C13 + 21: 6C9206FB7D349AC74D44352A4F5203F800AF34C1AEA8F1CF8C6AC491317DD1B5 + 22: 6A4C8E752F5D4B4774FC5CE600260B727DEF2850A2D4BC470E63E6E728DE9D7B + 23: A4F9221FF5E44E68CFA1576CF37A57BC7EAA1FC365BEAC7D369C414770DC3FBE + 24: D5CD0C791215BB022B7A07FE60A947AB436A4EC1CBC29CA60824A57CC6074CE1 + 25: 52BE7FD40C801C55380473D80AE191B273BB90F4750180F12C84B92F0378E102 + 26: 1B3F4246B2AD89AF381FAD9D993BAB24CCAC205576594D292489836F45E7038D + 27: 41903C7B3EA1F3F63FE734F54998682C97723336AF661DC988919FF7C0D8ECF0 + 28: B268AF3A3971754C8DF859C6A91BFDE7929CAE0C4F4CB08826990F02574D7E95 + 29: 137E134DCAF4348C629347DB5626DC85FEC2A9312B6B379CD2ACEF43D073983B + 30: 65333197B21CDE07F4A452656CE2EF447CAC4EB56AE0F25FA9AB1551A52A2E58 + 31: 182C11FF061A611473BB2357FB422EDEC582C80837CB0A838B43761E81E528CF + 32: FA34635F1D3AC2729AC5987EB59E01928457F325B4B51CA85A177813C5C5DDF7 + 33: D2D8FE4545DA9CD3AFD31D31425FA2B3CDE043C6B40DB542B81683C20303CD21 + 34: 09276AF3F77A8F06F9A3F84DD05DEFE5704F4B4A51FA27CB9EC162085037AE33 + 35: 36D1655C6F37FF56626234E8934B8922A66B978C78ADCAD8234D6A66C201F29D + 36: 3CE6E59BCB3B3EE8581E34EA5A92CD5C5D03C877A54ED9C8CEFF188125FC765D + 37: 2FF022CEC2F8D6C474C86237E747983D0833EB65A435925FCE17E780E4D83404 + 38: CF021C2A028F8101AB8173E35DEE507F5BE2FB2F133BEBF4AC6F1A3C420986F9 + 39: 51C501B8F6F85B3C36B630171F857E58622DAD1CAFE296D2371187F24D307A7E + 40: 9D96C19358BBC611B74B1844A69E12931884879CC2267245FE940B11662F905E + 41: 42248EEAA80C20C2181D982E2C612C422A483866BE662766B754D4090D19BBAD + 42: C1EFBEDE74C4FF558DD39C550AD0C078CD42D10B5183CA4CF626B1C8A7504802 + 43: 5474CD859A1CE6B80B04F40ADE7E010BD26AEED4BE01978DCED46445FEE8F93D + 44: 7E20B15A795D8278C911C8E8FEFC2A4DCF57BDE011DD9AD9F32A0FE758A829F3 + 45: E36DCBAC4C65F93D23F83FFA5F9FA8F6F542F96DC957A2952FF50C1836C7E1D7 + 46: 791E088D7D0A769E47CA3CFBC99723C549078E389D687D0E9A4F13EC6BA5457C + 47: E14485A2627415801FEDBCC1C34A6C3312940126EF62A90D94BBBE5E694CA89D + 48: 7EC11F122FA8D8858B6D4296B25E941D2C2FBD1E583D47B7EA24CFC9E4035A9A + 49: 8E13771E93C4181F1970BD92B9F8E349EB9C69F780D8E1BB0409B092F0122937 + 50: F24CEF726525070D3B44EA309A6A03396B22F6C48F0DDDD99539AC4DC62CE4EC + 51: 9731C326383BDD50E2AC8BE14E8B04418CECB904502F888658EC3AB27C44D926 + 52: 4BFEF43CD2AA9BD40275DE4DD7E6E41CFC9090D2C5EBE1C96D00F336E287A925 + 53: 2A5FD61773794FD7C959FFB29256C1C9A9C028CA1E4F1F2F5224C002B766989A + 54: 1BB1B592239447B5DE0395D94159996EA7CC4FCC7B9F66CCC5F0CFDC89586782 + 55: A79CF9DCEE3404ABF7F769698201647FD9D3FF61D629D0F58BB4B5579A427DB8 + 56: 62F7363B15F4DE76DD925C493B9D6D00D4BA0EF2A1F334C1D0F13B293AEB40D1 + 57: 441F67CC31781DD2986FC612B92DFADE871D81357F2487F5C86D94A8C6778D82 + 58: B4242D2BDE6758049D6BF3AC979CFBFA8590C8F9A964BAA53F4DE3529E958CE8 + 59: FE83EBD916FA2EFE514556D3F3410D5C571D26B97722517D182626D1E8D67D65 + 60: F886E1C50D032C1B893A53200F5D2C0DBC9B486CB0EEA56FBBB63A35BEAD01B0 + 61: CF232D81E9C18D7CABD90EEBD871C81A69BDF378AC06E49C2E8EFF969B75B670 + 62: 84932BAEBBA0FF9E1506788E6CFEFE7E6FA6B2E7132242B91417E1C5DB4F7706 + 63: 6165E4CBB15CDE01C6226E0015A47F710F8F8E1F2C296700033BB34D9212109C + 64: 93566F236D157AAE078D1DDB5CEBDBBA1520B5142E22A8915564345BA2AE1D63 + 65: C886E6814BE748285A10B28AE62DDACD85DB830CD2CF3A2BFA2F729C15F63618 + 66: E844F6E566C8E40CA5E650B938C4EA3C1EBB3F16A714F51F3303A089C09F9E62 + 67: CFD56A9CD3AB872B2E3893011341330B921513790C938BF09603F6DA2EC0520C + 68: 879E8707EB2F72C8FAE188F026486B3F0864B5EC43B7968FC516D3DB91AD72E5 + 69: DA5887C018000EDCF53D3E1E0B300FDB6619130A9D99EB5B80170D3308BF1036 + 70: 5EA935C5BC7A7D1F0A05865D059F9DE99D9C21CACAEE6335D896C386F2380F1A + 71: C4424CF106704451159FBF8AB1B69C0DCA84FBFF9D186702FDA7A99D1FD2DC77 + 72: C10B8C332565AB5A91C09BBB6E6E0187824CC5AEE0A2F9C607DA3B6DE15F9456 + 73: 807624E5CB1BC14F514C9F7C4FF1235D02B4FB9C8CEECE3458B20DACADD9BE0E + 74: C2B0AEEB41EEDFB383D1137F6C84D0331254ECAA1E1108E7D6C3F19BC28AA90C + 75: B5C1A6629434D8E47F192C10B79562D390CB91754755AFFF4DD6824AA9ECDA63 + 76: C6D12158451A0C2B14DDF34D2A512065F338D8B57EA821591B67C6A7D1F9BC5E + 77: 0311B0CE52BC5DBE8C837EA76D6D6259C2F4FCDC6C7BD2E16D78B67AB4149B8F + 78: 470739A11C5C5EB5860A0450AEB696AFC7EBF24DD95DC555E99B279FDD88B06F + 79: 7F57AD909EF4F62D7E762BBE1C9C3F18C4CCAF37805995CE86FABB7C762D1FF6 + 80: 9A1198BAD957F2E411297E1D17B627AFB6C842437C0ADE5879EA249021D1F0CD + 81: 7FC44253FA19DDE0A9FE8B116A0D01BF95A3077440C1A5D11B9614B6429DF505 + 82: F056FFB3833ACD0379144757E9816953AB097191533DC8A57AFFD1D127B38C4A + 83: CCD3FA40CC2D2114A5E9B3325F6584A4DF488E1B34BA3E2D1528327A36F352A9 + 84: 04203C3B8F1FFD61FF3D0134C6172D39C97B94B962B2ED7BE70070F0996DA57A + 85: 157CA56DB5039FB8BF536DADEA456EED976AE7DB54372EF71750852A1BF0542C + 86: 910BA7725F46EE646C270C7E82C5CFD2C9066FC0D88FB2820BA963C26DF1F465 + 87: 867441F91E3CA3E5EA5DB6269B8E30BAF5F6FD2BD56FB3FB715D4A8C7810CC71 + 88: 6701746ADDF00166C676CBA3F6CEC7BE379119C00F11011537ACD99BDB3CE0C7 + 89: 6D6E112EEC5B237AF3927A9A2ABFE7E4669FC15C5AD379D072D32B1D255BDCFB + 90: 986F414001210C8F32AA79DBE9EF3D7375E75C51271B7A04B366C67AAE1E4C87 + 91: 4AE6B2E1F2461A55CF44D92390BAA0492333A9F25645CBE1352CFBC5B42AFA2B + 92: 6A529A8E765E6988300F495E9B73A651C28E39892F0B31B4D5C43FAEB06F3870 + 93: 2228C5374B0B93CBBA4D4012362C6207AD2FF0CFA0DA0C5FE5622772B1885976 + 94: 2DAD3FA1D4856E95B67B261A5EBF6C5AFF149C5A7BCA25130940CA9E70CB6251 + 95: 6529643CE86E9FAF589409403F6DE23908FB91499C8AD09805AAD6C7F3EC5751 + 96: 2EDBD8866011F112124F30774E9CE85E3BEA3C2CCF98FD8757046A2943DA59B6 + 97: 2B987812D4479D2F095A5A22AAE0B8A77A1BDECDEBDA16DCB987CF3974003E81 + 98: 95BE171D4DC68DC32DA1DD5A1A31808C0A324A8FEAA4044F0CBE7304F4B3603E + 99: 7D4EAC94A68E328B800BE8D9BB1772C268450B7A3C9959D0729F036CDB8B8BB6 +100: 4B2833C158DD41614B76E37F18889243BD6B4A744E36DE60920A2F89E409C64E +101: B0992CB78BE5CDA48BF503DE1D3B4EF88AEFFF54EE6CF8A2BE14CA48BC400D55 +102: 0CD08EAA77E6A6F48E1E4A9371C17EC66B5D3B27A28A00E93D633CB68097CC4E +103: 30821BF5C6770CB2071A04BC764FFC859EE9FD51149A0FBF6F45FCACE6523D44 +104: 67916A4F629B6CCC733EDDE300D316EB405BC04E7D381738456E2AF39601DC70 +105: AAC90FA00921904EF66D6BDF92DC29F478E1D394CC4E8ECC68F71882062380FA +106: DBF54DC0B588C2DE7DD9FF941868873D60222E77990C16CA2892B32B326EFFC6 +107: FE698FFCFAA632E75EA1B943889ED4D090E91E846AFC78053C8B72D8019C56F8 +108: 3FAACA4E09E7667DEAAB83ECB6D430E9DF80C0D1F69B05981DA052D6A0BCD977 +109: 32302DB834A491D160AAF5C0A66AD90CFAFEEA5855E6D0283BA331B66777DA46 +110: F3214C9CCA8FA3682D22660A541625D55F2B3B7D7B56362A861D4A1C75056E36 +111: 46EA8FF040518238FB6E34B688209BDCD18B31672C4BA28271045F8C8C312733 +112: 1C7B0125F4F56AA3E7104B10B25CE1C98E7668720F9A9E2EB21B6DE36BBC62E7 +113: 2C828958C3F34A2587DF239F258F52B3ECB599F67E96A4064DA2D4FA1A955F2C +114: CFDD1BEF2646546BC6FEE51B84AE9A056A1F3D3FF404F719C5EA889AAD00594A +115: A02A9AFC0B47E0F4E79924CD3FD2A9E242664360172B61298486D0CC6A9583CA +116: 7708158049314AFDEB7C9B23B18E27F556D480057AAE126114167688B2D5EE0F +117: 8990E02F7553F6077D6DA698CA76688E64F52FFC93A975085D2FD36D9541A2F9 +118: 28470FFDEC4F1C82E0A09F1D2A771DFB0D785F7119E401B6E5A42029DFC88C32 +119: 8F3EA392A89A7119982D6634660DB1A95F35D68267A2235E3255998A857F4FBF +120: 6BABEE35E6A1515AF9D6255109C24F3C08897829422C6225D235FD4C8527E9EC +121: 501BF851D9377E2F02E6DC2DA58795B5A7337D94EFBEA64BCBAF0B3DF11E240C +122: 00825B1AB35F89279C4869826C159F5910CFFDE3AE20AAB7BCA13EC8263E12E5 +123: 722D468220D61A129D766E589968B196E4136B39C4E83B5CA215050C4CC7107A +124: 76ABE4F014C7CAF037FC6B87529F8031DBA51F55BA3C00C61C8AAAD666C43098 +125: 60434971512E75B7325472797C7B11BC4932EC6561050EBF8A38698BDDC84B76 +126: 07F7BA45D5551D5DBD3C3926619235A7EE880396D67A63398053DA8E3376BCDB +127: BCA3436D828517A6A6893A9E309E06E7B7B29C6E3F78B4814B23EFE149962980 +128: A9E7985473CA09DF1510D83B572F72375430756C4A661B00724AFEB8B75DD0A5 + Hash: chc_hash 0: 4047929F1F572643B55F829EB3291D11 1: 8898FD04F810507740E7A8DBF44C18E8 diff --git a/notes/hmac_tv.txt b/notes/hmac_tv.txt index 17270fe3f..5cd0cea25 100644 --- a/notes/hmac_tv.txt +++ b/notes/hmac_tv.txt @@ -6053,6 +6053,137 @@ HMAC-md4 127: F7DEAF52378FF735B2D171B17EF573D8 128: B4FA8DFD3AD4C88EABC8505D4901B057 +HMAC-sm3 + 0: FDA7C78D15984D8771F59F20A69D195C6E237070D37EC962E167326E517433DB + 1: 617D49CB0D2E65E6D40338631AA35620A150669B14D3B36BECFA3B4A04610EA9 + 2: F0F69EBA9D1F9F0A76F9C7B2E690BDE43DDC49009B820D8E0126C2ECFAE426AB + 3: 43D562376EBACD17A91696FEA0FD06D7AB5B88A8845208B7405797469AF4E9C0 + 4: 6F9776F31DAEA542D1FE17D9E8F03B22F420C71506E048C97E11C61270B092E8 + 5: 1C99064F49994C32ADAAAB111B0F537EB892449065B47E10B6B4B4CE8D58051E + 6: 321DC2AF96E4B6C90FD2924E9436CAAFB13FF98FD7C00F32D66F6A99E256F7C7 + 7: 21AB9DC39C31DDFD06D8A6A4120A022BEC1B9FF85C7BA5982A12C540558D7843 + 8: 2220C299409746CE30B3BB1E15022ABB72B1519D5F20B7AB3FF3D861E0503BCD + 9: 8EDEA1BD3178A5B23013A603F518EF883C9E3F3C8B427B0DA59865072841557B + 10: F0F23D78EB6D6052EA520D40BF8634EB3F4CE9AE505D0B61232B97DF61264CAC + 11: 352E0D68D3D30E799BE200EA8B2DAF47278292C45D1787BCFCA1BEDEF8986DF4 + 12: 7A0C0AD88D42EFF62A705D52EAE0967DD1FCCC12D97F1D7F7B4F024E90847E38 + 13: D6B74CEAF3A49AB888C874352051DC9B84020DF8EFBC8C16C2AB3410C5DF17E2 + 14: B8CFEC6CBDD7C6E40EEFABADFC535B2AC371D80FB7EAAC58A6AD1A741A5F94FA + 15: B4D0E042DBFEAED267D122A725D9AD0AE1C0811F27941854CC24FE87F8BB3122 + 16: 87FA1B3991FDCDDBAE670776DD787424923047CCA18F5908F0DBC11A8032DDF5 + 17: DC56D1C961A832B23691D0017FD0F25E9239643AFE9F168483EB3750FEDD2268 + 18: E232D251E702732F4AB7D698A157E398078835E8E5FD30D14A54E5BC46E8F292 + 19: 4D7F888B9E635C1189AF264004D442FDA65A4C40E461AEE8E5ABD4DFE6EC0B9F + 20: 55CBB73B388DC86C1831A37093967FF15D986D8DDD0CA61189D80D6D8A87A667 + 21: 04FD2A4221EE565012A39216A66DCBC50FA259BFA470C89388EDFD3B8F6C21EA + 22: 7662B2B11A159E3C453D1A96C3EB60BC92CFC9F34E08BF5EE017A2517BB9CC02 + 23: 0F954E8B243AED1DCEC72E563B02CBFFC032F91C613010332CD7BAC1D1E3D24E + 24: 4030CA3461619B9D8A5F38B20CD2D29458A3F036FD274056027B3645DF858F63 + 25: 2123F1819732FA2A6785DA76D304764AEBC15CE5C1C4F4FBE441EDE7F23D821B + 26: 7CA7D551BDFDE5CC42A4BA2EDEAA493753AEECE03730364B1B977CB2654B9C67 + 27: 27A57C09732E9B727848CD085098BE3E4AC6B8C94EF424384B4CB1E8DAE3EC41 + 28: 7AA2574C5CEA298E2F62D1E555B3995AD94A33C0D6B4ED1E0A5F4491C4BB8D9B + 29: 96204A4D5C49A08E6DF8C586837A5FBE84C524145DF28461158CF8ED16DC49D0 + 30: 797F92BA0573B7B50D79B74A5918927DA02A13E45B8BF2C40824852417743503 + 31: 95A1E1510DD9F71E9CC5D9E98A5605B106C0B2E700E4DF30C753F2C01C702191 + 32: 627D1EC821E89223D52ED8160606118712F9ED8157348726625F6395AA35346F + 33: A77D4DDC40FF552F6DB39B8907AF3C548ACF9D32D6A809E34E9A554802D0D15C + 34: 2AB412A14044430F4680FD090881CDAF0DE6FD2D3D60A925A8C3DD0662D8E30C + 35: FDEC326A6197D103C445940DB1FB7AA2BC7D6F92B2685139BBDB4B915FF141F5 + 36: C026D1871252E156F29689F10586BFC3E0EE3F93FFEE580010BC4A4AE1880961 + 37: 708E875DF37FE36144A46C623A36FD24018078F6585ABF4F09C0326C8B18C253 + 38: DEB6B61641523D57335E5F66B5B324F6649B86119A7D7C5E6603DE55D5D6BB30 + 39: 70F97D866A1183ED59E38D866B28BC570B9AD2A40A2EDF39464A32B10D474F40 + 40: B790F4A66BED45EA332BD096F68FE8F63B5B0ECD2FAA247B0636A7F62574D7D1 + 41: 2D938A0D7F1E9309AB1A519BCD57AC206063738CD4EED18332505D8849CFC356 + 42: 366C9828FA31E8B4F5691ADAA1E72AC80B8463A3E374A5087EB29ECE18761EF8 + 43: 0B95346AD2C489A79BF7275CA27E57A59CCF925B8D7D6455C00725A6A091E5BB + 44: 84A7E62264AA7750E3C01D737015493A00090DE9EAA1100BD23B70586FE89BF5 + 45: 2382C631C93761326B36061BA2320AAE3AE86DF1C6971D5CA0346BBCAA133DA8 + 46: 2A1174BD21D53783B778F74BCDD9F7E23D3756C0ABC04A82510C9FBAEA2C972C + 47: 8FEF6E55EC97B90C32E369C6C3BE9FBB67BA161D586AD22C91A59EF37B53D33C + 48: 8196E30D810E3B8572DC442176983E91F2FCAF6B30EF7DE43509709C699CA901 + 49: 6CE3EEA9753B3494ECE17A04C2078F87172A6630DA80C50E3927BCE9754523B6 + 50: 38483A4449FDA7DED6CCE12AA646189805EA24789512653A1D6A6C9B0519F9A8 + 51: 34F239065041B4A0D8C0B322761D9B10AEE2564C34D4873B0E679EB4A6CF6461 + 52: 67DE337F86BC9F19D0EC034188932CDCFDB9A558130D5FE6DB4043725A8D3EDA + 53: 7127E9B9B4B72B7DB676D89584EBE27D7393F3FCAB96E52FBFF7ACF0E1B638A2 + 54: 1F595D3EC2CBB70548146D06B23094247D5FD21A85ABC61368321D9656481E3F + 55: 8747F4684BF950AF1C6C9C91927108E7F28D6A0CF85E6B9CF7A579356C89C10E + 56: 75F5648852677892870B21D7CFCD1F99F6C3DB24EFA44D5B9271525D8BF6A2AF + 57: 1827E88B3FD984B7C527A6E38CB775BD088478BF89B76C6C4670E24D550500A5 + 58: FDC378293FF9CD28E26409E228F8E2FEDCD2FE103B2664F66698438B90E24344 + 59: A5919F1DC6D328B7E91F57EEF4AE1806EDC2EC39980642C32B5DBB7FED341A13 + 60: FB5CAB3098A9C9464A86C529F83FC55029478AEFFCB2747E81071DBDCBD8CB07 + 61: BBB3D6EFCD7024C4B5EBC8E6E1462888CCD05C6A5D54FDA480E3E4DC70E697F7 + 62: 45024D25E0B4BE45704B0BB0FA75DF3D35912F9E9851D8F4EC6152C8B7329AE6 + 63: 77A369C752335EE25F1CEFB5CCFEA5338832059E9C973868EABA30B238A49138 + 64: E29DD2084287275FED87809068165B3BCA7DC3C40E74BD77E862079AA7134426 + 65: 82CAAD784EB51C22E1275B653E88C4A0E54CC32B071553612718C5897D5F5BC7 + 66: F5B374CF37D8880594F6B6193D0732309E55E68EAD7A1526BD275FD2B705CBE1 + 67: EFF15666D4E39457C611B2BBF569F74056594778E4F812D51F9E8E74439F35BF + 68: 66E16B57F8279454B3F7DD44970E8DDCF6560F3066117E13CD1C2A1D771F1E87 + 69: 4B9D7831322C1238BA57B6774359A22D2C69F646CFC5BE66E8943EFFF2287889 + 70: 6CAA665C55B0D237AA647A499A82C7334F551B456F5841884CFFBCAF60F3A036 + 71: EF5CE22D8AB45A933631EDAA542D568D83780169808C954E052D810FB3E33330 + 72: 9B64571987EDC852F762B0B7D182F5F0253B3B52BC639C16B6121E96FD578E67 + 73: 076B0DF0333BB5EC7AE694EF1B803700A27A1B59DBDB9A429E91EFB4EBB0DE1F + 74: 8C9CAA85D262C2BD03126B60161EE34B7DF152314ACAE843EB50D85870DAFE9F + 75: 81C4B1DB61FECE8691E6C7C7C8EAF540BB96589D90DFE1AC1553F7C70F0127DC + 76: F0CBC76277EF1E2A80A30081F5B96EE1E671986B52FD8E0A7EDB6059E210D7A0 + 77: 2815C4A53030ED946006FA06C1E2B8111D434BFF9ABFD18B8C76DBE51511A3C1 + 78: A87B8819CDC21A993C1D456878F7A402BF8FC517F0C8784CB882C4E6E2245413 + 79: B014D6565ED29088B5AEB1323DD08BDA6776695B1800878C91FAEAEB05EB2A1A + 80: 7F472FA85204CF5F484DF4D5C52CC391BD4DBA24DA07BFC82C3F870796C2B795 + 81: 8DE428F49F03F0F6BACF0EBCA947FAF916B2466061D6EC1898316E0AD2716D40 + 82: F1F807A356C9209CF2649E5DEB6A4C357841548AD82B239617A11D94EF6261F3 + 83: FC1FC2303153AC696E88FEEDA6879C4DD104DE2E7174599A21BE594896F30714 + 84: 197F79D306A358927A78F0D71C85B9295071385B7CDD96A8034BF4FEDED9DE25 + 85: 99DB23774C0D04F81F2E9188DCE28628BF3BC5B04610AC56CC6B116042DD0794 + 86: 158A3B8B4C3EF4E80971CCD6BD2F013042C263407691A2BAC357158797466F00 + 87: 77DF54967B43EDEE572BFE345CD9257A525D81F27AC15F0D7821E8FE7A9A30E9 + 88: 4D699FA49D84CC0C4B99052108575AFCA5E392D120CFE3703C39436EAED5A171 + 89: 90E4507A00187A72752E87ACD68665A90EBD1D1B6B01DEC924A25270EEB7C39D + 90: ADB4298548F9F99CCCFB2ECB31A6A843A74361FF48B1C60D2733EDB8B7962B21 + 91: A6AF395014B32E38E8412C242FDF2F680C5CDA058750027B23F52492615E54C7 + 92: E4A454D0A5AC0003D5EF4FC924890AF27DFBE5B882ADD8AD0F8CEB1422EED0EE + 93: BC79E235F3176A7DE9A1D7CF7363FCF8C92F42B520F613F4E8E613F914B90CCC + 94: 7CFEF638B210C64DB3D4AF304BE75699236E4706933A17B33EB19B74AB071638 + 95: 9B1B80D29662A927AA6E18C29CB7C4C344C252D9BA5C524B1E8801F8F3BD7E27 + 96: DABDF3450AC41C3FF33B2F8673372C06F52FBB5DF164B96C5A32F8C06EF14158 + 97: A2BAD8C4A44D1731C9DC610518628BA43EBE49540C5F72D74C0FBA3B534486C7 + 98: FFBF8FB40057112AA05D84FBACF2105A92F9CDCA5AA39E8CB91F68936F8B9292 + 99: AA92083B20D9DC114CFB154384926BAF36BF435AFA037C5687AE4B26589E57BF +100: D9F588A127C332A147B24A7D4A207ACE3C7B2BB01F136ACE869525803404F8E1 +101: 1EDC2C83147428DB0C0C226B0A92901DAD66B8D1C1E995C7AFE16CD328BE1D50 +102: 91C72518543373893805E3B9974315D0728476C5E5D551FC909BD2A32F96F9E5 +103: 73DA6EB942A9146992F089BBA9167D9D175E6A7E9705FD40841F23BEBA923E37 +104: 7F477EF5C2CCDBDE7257EB670BE18B943FBB8CDEC0C681C02575FD9477566862 +105: 4ACB9C29DEEF8B5058582CAC99C8106686DC8B14D3DD4D8CD057B5CDE3182416 +106: 6806370A302599727B3B2C93EDEAE06155568F82FDAA6A768776B382887ADDBA +107: 35B38613156EF52C643A4CCD427DA0415563C481ED1933F6A08D19B9F3E4965F +108: D7EF3FFBB64D1EDA0E052505C88340D5488D60EE8F877A1ED65C01C3FFF88838 +109: 3D486B2407C38F60D40866C6FE2BC6FFAA2778297BD2442488F9FFC323051E1E +110: 3777FDD5F2F2E9A8B0053AF2573AE885ACEBAE28F24F3A56777FF877716AD7DF +111: EF076FD597E88ECB8A6E535D3DFABF2B4D13B34AF0DDA28AD89EFDD1618B9D66 +112: 19D6FFFAE75E20781CA08F3E5351C77826C6DC298AAC96D4124C3A488565E4B5 +113: F10FDDF2236CF7CD9E32FBC3C4E44664AC855CE42D5676D46BCF21507C7FD7A4 +114: D5873662FDF61D85D14D7E74B6B7779EDC9236DD774EA8FE60561944F593E48E +115: 3ED1A43C031FF6A991FF1FB3F5196C41D131B0387D70789DC4B5ED32956CB258 +116: 7E4DEF340CFC9BC59FDD03D8AE55EAC078726CAE561403CED0227C184E6667F7 +117: 3E72B9A2835309A6556D275F4E9AB6F3C35657B451FB9670D10CB7288F55BB89 +118: 6242C423C03C058C5294ADCB959F0FF62FC0819696EF7F2AEE0A93A57FA934D8 +119: 1B6C1DAB2B50E92A74D016CD136CE4B2B8BA6EC0DA8AB97CA7F16FAFA914F8D0 +120: E511EA25C6C73696889E5480BEFBAA2401DECBEDDC1F87BED9EC48808C8AC003 +121: FD59BDB6357F877EB28500E09AD721B65ADEEC4854522E7A1288E90D95DB146E +122: A772599D4F1EBE527D80C1132589F0E9C1B8649C60CB551B126DD7772B537E8B +123: 28D3590C54883B8D8ED6707486D209AB1A2A25411E30D128FC1A43F6119C54DF +124: C9838385D4E9DAC898798E08F96367E0190FAF240EB3AAA8E1989A06FD55229D +125: 10B281D771D85DC89B766FBE9AF19B1584F6A2214E5A5B8D682299648C53F7D3 +126: DAF8137A6A6EF0827838570D4A48A75C02246C9BCA6E94B19CB5737BBC7B0367 +127: CD2986F99AEC715AA580BE75AD1735C985506247A57C5FC51C03E60B3631D4C9 +128: 2762E9366F3C017AE2AC0ED01ECEDCFD6907A3BCEE9B00A8458FB5833225FCCA + HMAC-chc_hash 0: 0607F24D43AA98A86FCC45B53DA04F9D 1: BE4FB5E0BC4BD8132DB14BCBD7E4CD10 diff --git a/src/hashes/sm3.c b/src/hashes/sm3.c new file mode 100644 index 000000000..acc73aee6 --- /dev/null +++ b/src/hashes/sm3.c @@ -0,0 +1,423 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include "tomcrypt_private.h" + +/** + @file sm3.c + SM3 hash function (GM/T 0004-2012) + + Based on the Crypto++ implementation by Jeffrey Walton and Han Lulu, + which was placed in the public domain. + Also see https://tools.ietf.org/html/draft-shen-sm3-hash +*/ + +#ifdef LTC_SM3 + +const struct ltc_hash_descriptor sm3_desc = +{ + "sm3", /* name of hash */ + 34, /* internal ID */ + 32, /* Size of digest in octets */ + 64, /* Input block size in octets */ + {1,2,156,10197,1,401}, /* ASN.1 OID 1.2.156.10197.1.401 */ + 6, /* Length OID */ + &sm3_init, + &sm3_process, + &sm3_done, + &sm3_test, + NULL +}; + +/* Permutation functions */ +static LTC_INLINE ulong32 s_sm3_P0(ulong32 X) +{ + return X ^ ROLc(X, 9) ^ ROLc(X, 17); +} + +static LTC_INLINE ulong32 s_sm3_P1(ulong32 X) +{ + return X ^ ROLc(X, 15) ^ ROLc(X, 23); +} + +/* Message expansion */ +static LTC_INLINE ulong32 s_sm3_EE(ulong32 W0, ulong32 W7, ulong32 W13, ulong32 W3, ulong32 W10) +{ + return s_sm3_P1(W0 ^ W7 ^ ROLc(W13, 15)) ^ ROLc(W3, 7) ^ W10; +} + +/* Boolean functions for rounds 0-15 */ +#define FF0(X, Y, Z) ((X) ^ (Y) ^ (Z)) +#define GG0(X, Y, Z) ((X) ^ (Y) ^ (Z)) + +/* Boolean functions for rounds 16-63 */ +#define FF1(X, Y, Z) (((X) & (Y)) | (((X) | (Y)) & (Z))) +#define GG1(X, Y, Z) ((Z) ^ ((X) & ((Y) ^ (Z)))) + +/* Round function for rounds 0-15 */ +#define R1(A, B, C, D, E, F, G, H, TJ, Wi, Wj) do { \ + const ulong32 A12 = ROLc((A), 12); \ + const ulong32 TT0 = ROLc(A12 + (E) + (TJ), 7); \ + const ulong32 TT1 = FF0((A), (B), (C)) + (D) + (TT0 ^ A12) + (Wj); \ + const ulong32 TT2 = GG0((E), (F), (G)) + (H) + TT0 + (Wi); \ + (B) = ROLc((B), 9); \ + (D) = TT1; \ + (F) = ROLc((F), 19); \ + (H) = s_sm3_P0(TT2); \ +} while(0) + +/* Round function for rounds 16-63 */ +#define R2(A, B, C, D, E, F, G, H, TJ, Wi, Wj) do { \ + const ulong32 A12 = ROLc((A), 12); \ + const ulong32 TT0 = ROLc(A12 + (E) + (TJ), 7); \ + const ulong32 TT1 = FF1((A), (B), (C)) + (D) + (TT0 ^ A12) + (Wj); \ + const ulong32 TT2 = GG1((E), (F), (G)) + (H) + TT0 + (Wi); \ + (B) = ROLc((B), 9); \ + (D) = TT1; \ + (F) = ROLc((F), 19); \ + (H) = s_sm3_P0(TT2); \ +} while(0) + +static int s_sm3_compress(hash_state *md, const unsigned char *buf) +{ + ulong32 A, B, C, D, E, F, G, H; + ulong32 W00, W01, W02, W03, W04, W05, W06, W07; + ulong32 W08, W09, W10, W11, W12, W13, W14, W15; + + /* load state */ + A = md->sm3.state[0]; + B = md->sm3.state[1]; + C = md->sm3.state[2]; + D = md->sm3.state[3]; + E = md->sm3.state[4]; + F = md->sm3.state[5]; + G = md->sm3.state[6]; + H = md->sm3.state[7]; + + /* load message block (big-endian) */ + LOAD32H(W00, buf + 0); LOAD32H(W01, buf + 4); + LOAD32H(W02, buf + 8); LOAD32H(W03, buf + 12); + LOAD32H(W04, buf + 16); LOAD32H(W05, buf + 20); + LOAD32H(W06, buf + 24); LOAD32H(W07, buf + 28); + LOAD32H(W08, buf + 32); LOAD32H(W09, buf + 36); + LOAD32H(W10, buf + 40); LOAD32H(W11, buf + 44); + LOAD32H(W12, buf + 48); LOAD32H(W13, buf + 52); + LOAD32H(W14, buf + 56); LOAD32H(W15, buf + 60); + + /* rounds 0-15 (R1) */ + R1(A, B, C, D, E, F, G, H, 0x79CC4519UL, W00, W00 ^ W04); + W00 = s_sm3_EE(W00, W07, W13, W03, W10); + R1(D, A, B, C, H, E, F, G, 0xF3988A32UL, W01, W01 ^ W05); + W01 = s_sm3_EE(W01, W08, W14, W04, W11); + R1(C, D, A, B, G, H, E, F, 0xE7311465UL, W02, W02 ^ W06); + W02 = s_sm3_EE(W02, W09, W15, W05, W12); + R1(B, C, D, A, F, G, H, E, 0xCE6228CBUL, W03, W03 ^ W07); + W03 = s_sm3_EE(W03, W10, W00, W06, W13); + R1(A, B, C, D, E, F, G, H, 0x9CC45197UL, W04, W04 ^ W08); + W04 = s_sm3_EE(W04, W11, W01, W07, W14); + R1(D, A, B, C, H, E, F, G, 0x3988A32FUL, W05, W05 ^ W09); + W05 = s_sm3_EE(W05, W12, W02, W08, W15); + R1(C, D, A, B, G, H, E, F, 0x7311465EUL, W06, W06 ^ W10); + W06 = s_sm3_EE(W06, W13, W03, W09, W00); + R1(B, C, D, A, F, G, H, E, 0xE6228CBCUL, W07, W07 ^ W11); + W07 = s_sm3_EE(W07, W14, W04, W10, W01); + R1(A, B, C, D, E, F, G, H, 0xCC451979UL, W08, W08 ^ W12); + W08 = s_sm3_EE(W08, W15, W05, W11, W02); + R1(D, A, B, C, H, E, F, G, 0x988A32F3UL, W09, W09 ^ W13); + W09 = s_sm3_EE(W09, W00, W06, W12, W03); + R1(C, D, A, B, G, H, E, F, 0x311465E7UL, W10, W10 ^ W14); + W10 = s_sm3_EE(W10, W01, W07, W13, W04); + R1(B, C, D, A, F, G, H, E, 0x6228CBCEUL, W11, W11 ^ W15); + W11 = s_sm3_EE(W11, W02, W08, W14, W05); + R1(A, B, C, D, E, F, G, H, 0xC451979CUL, W12, W12 ^ W00); + W12 = s_sm3_EE(W12, W03, W09, W15, W06); + R1(D, A, B, C, H, E, F, G, 0x88A32F39UL, W13, W13 ^ W01); + W13 = s_sm3_EE(W13, W04, W10, W00, W07); + R1(C, D, A, B, G, H, E, F, 0x11465E73UL, W14, W14 ^ W02); + W14 = s_sm3_EE(W14, W05, W11, W01, W08); + R1(B, C, D, A, F, G, H, E, 0x228CBCE6UL, W15, W15 ^ W03); + W15 = s_sm3_EE(W15, W06, W12, W02, W09); + + /* rounds 16-63 (R2) */ + R2(A, B, C, D, E, F, G, H, 0x9D8A7A87UL, W00, W00 ^ W04); + W00 = s_sm3_EE(W00, W07, W13, W03, W10); + R2(D, A, B, C, H, E, F, G, 0x3B14F50FUL, W01, W01 ^ W05); + W01 = s_sm3_EE(W01, W08, W14, W04, W11); + R2(C, D, A, B, G, H, E, F, 0x7629EA1EUL, W02, W02 ^ W06); + W02 = s_sm3_EE(W02, W09, W15, W05, W12); + R2(B, C, D, A, F, G, H, E, 0xEC53D43CUL, W03, W03 ^ W07); + W03 = s_sm3_EE(W03, W10, W00, W06, W13); + R2(A, B, C, D, E, F, G, H, 0xD8A7A879UL, W04, W04 ^ W08); + W04 = s_sm3_EE(W04, W11, W01, W07, W14); + R2(D, A, B, C, H, E, F, G, 0xB14F50F3UL, W05, W05 ^ W09); + W05 = s_sm3_EE(W05, W12, W02, W08, W15); + R2(C, D, A, B, G, H, E, F, 0x629EA1E7UL, W06, W06 ^ W10); + W06 = s_sm3_EE(W06, W13, W03, W09, W00); + R2(B, C, D, A, F, G, H, E, 0xC53D43CEUL, W07, W07 ^ W11); + W07 = s_sm3_EE(W07, W14, W04, W10, W01); + R2(A, B, C, D, E, F, G, H, 0x8A7A879DUL, W08, W08 ^ W12); + W08 = s_sm3_EE(W08, W15, W05, W11, W02); + R2(D, A, B, C, H, E, F, G, 0x14F50F3BUL, W09, W09 ^ W13); + W09 = s_sm3_EE(W09, W00, W06, W12, W03); + R2(C, D, A, B, G, H, E, F, 0x29EA1E76UL, W10, W10 ^ W14); + W10 = s_sm3_EE(W10, W01, W07, W13, W04); + R2(B, C, D, A, F, G, H, E, 0x53D43CECUL, W11, W11 ^ W15); + W11 = s_sm3_EE(W11, W02, W08, W14, W05); + R2(A, B, C, D, E, F, G, H, 0xA7A879D8UL, W12, W12 ^ W00); + W12 = s_sm3_EE(W12, W03, W09, W15, W06); + R2(D, A, B, C, H, E, F, G, 0x4F50F3B1UL, W13, W13 ^ W01); + W13 = s_sm3_EE(W13, W04, W10, W00, W07); + R2(C, D, A, B, G, H, E, F, 0x9EA1E762UL, W14, W14 ^ W02); + W14 = s_sm3_EE(W14, W05, W11, W01, W08); + R2(B, C, D, A, F, G, H, E, 0x3D43CEC5UL, W15, W15 ^ W03); + W15 = s_sm3_EE(W15, W06, W12, W02, W09); + + R2(A, B, C, D, E, F, G, H, 0x7A879D8AUL, W00, W00 ^ W04); + W00 = s_sm3_EE(W00, W07, W13, W03, W10); + R2(D, A, B, C, H, E, F, G, 0xF50F3B14UL, W01, W01 ^ W05); + W01 = s_sm3_EE(W01, W08, W14, W04, W11); + R2(C, D, A, B, G, H, E, F, 0xEA1E7629UL, W02, W02 ^ W06); + W02 = s_sm3_EE(W02, W09, W15, W05, W12); + R2(B, C, D, A, F, G, H, E, 0xD43CEC53UL, W03, W03 ^ W07); + W03 = s_sm3_EE(W03, W10, W00, W06, W13); + R2(A, B, C, D, E, F, G, H, 0xA879D8A7UL, W04, W04 ^ W08); + W04 = s_sm3_EE(W04, W11, W01, W07, W14); + R2(D, A, B, C, H, E, F, G, 0x50F3B14FUL, W05, W05 ^ W09); + W05 = s_sm3_EE(W05, W12, W02, W08, W15); + R2(C, D, A, B, G, H, E, F, 0xA1E7629EUL, W06, W06 ^ W10); + W06 = s_sm3_EE(W06, W13, W03, W09, W00); + R2(B, C, D, A, F, G, H, E, 0x43CEC53DUL, W07, W07 ^ W11); + W07 = s_sm3_EE(W07, W14, W04, W10, W01); + R2(A, B, C, D, E, F, G, H, 0x879D8A7AUL, W08, W08 ^ W12); + W08 = s_sm3_EE(W08, W15, W05, W11, W02); + R2(D, A, B, C, H, E, F, G, 0x0F3B14F5UL, W09, W09 ^ W13); + W09 = s_sm3_EE(W09, W00, W06, W12, W03); + R2(C, D, A, B, G, H, E, F, 0x1E7629EAUL, W10, W10 ^ W14); + W10 = s_sm3_EE(W10, W01, W07, W13, W04); + R2(B, C, D, A, F, G, H, E, 0x3CEC53D4UL, W11, W11 ^ W15); + W11 = s_sm3_EE(W11, W02, W08, W14, W05); + R2(A, B, C, D, E, F, G, H, 0x79D8A7A8UL, W12, W12 ^ W00); + W12 = s_sm3_EE(W12, W03, W09, W15, W06); + R2(D, A, B, C, H, E, F, G, 0xF3B14F50UL, W13, W13 ^ W01); + W13 = s_sm3_EE(W13, W04, W10, W00, W07); + R2(C, D, A, B, G, H, E, F, 0xE7629EA1UL, W14, W14 ^ W02); + W14 = s_sm3_EE(W14, W05, W11, W01, W08); + R2(B, C, D, A, F, G, H, E, 0xCEC53D43UL, W15, W15 ^ W03); + W15 = s_sm3_EE(W15, W06, W12, W02, W09); + + R2(A, B, C, D, E, F, G, H, 0x9D8A7A87UL, W00, W00 ^ W04); + W00 = s_sm3_EE(W00, W07, W13, W03, W10); + R2(D, A, B, C, H, E, F, G, 0x3B14F50FUL, W01, W01 ^ W05); + W01 = s_sm3_EE(W01, W08, W14, W04, W11); + R2(C, D, A, B, G, H, E, F, 0x7629EA1EUL, W02, W02 ^ W06); + W02 = s_sm3_EE(W02, W09, W15, W05, W12); + R2(B, C, D, A, F, G, H, E, 0xEC53D43CUL, W03, W03 ^ W07); + W03 = s_sm3_EE(W03, W10, W00, W06, W13); + R2(A, B, C, D, E, F, G, H, 0xD8A7A879UL, W04, W04 ^ W08); + R2(D, A, B, C, H, E, F, G, 0xB14F50F3UL, W05, W05 ^ W09); + R2(C, D, A, B, G, H, E, F, 0x629EA1E7UL, W06, W06 ^ W10); + R2(B, C, D, A, F, G, H, E, 0xC53D43CEUL, W07, W07 ^ W11); + R2(A, B, C, D, E, F, G, H, 0x8A7A879DUL, W08, W08 ^ W12); + R2(D, A, B, C, H, E, F, G, 0x14F50F3BUL, W09, W09 ^ W13); + R2(C, D, A, B, G, H, E, F, 0x29EA1E76UL, W10, W10 ^ W14); + R2(B, C, D, A, F, G, H, E, 0x53D43CECUL, W11, W11 ^ W15); + R2(A, B, C, D, E, F, G, H, 0xA7A879D8UL, W12, W12 ^ W00); + R2(D, A, B, C, H, E, F, G, 0x4F50F3B1UL, W13, W13 ^ W01); + R2(C, D, A, B, G, H, E, F, 0x9EA1E762UL, W14, W14 ^ W02); + R2(B, C, D, A, F, G, H, E, 0x3D43CEC5UL, W15, W15 ^ W03); + + /* feedback */ + md->sm3.state[0] ^= A; + md->sm3.state[1] ^= B; + md->sm3.state[2] ^= C; + md->sm3.state[3] ^= D; + md->sm3.state[4] ^= E; + md->sm3.state[5] ^= F; + md->sm3.state[6] ^= G; + md->sm3.state[7] ^= H; + + return CRYPT_OK; +} + +/** + Initialize the hash state + @param md The hash state you wish to initialize + @return CRYPT_OK if successful +*/ +int sm3_init(hash_state * md) +{ + LTC_ARGCHK(md != NULL); + md->sm3.state[0] = 0x7380166FUL; + md->sm3.state[1] = 0x4914B2B9UL; + md->sm3.state[2] = 0x172442D7UL; + md->sm3.state[3] = 0xDA8A0600UL; + md->sm3.state[4] = 0xA96F30BCUL; + md->sm3.state[5] = 0x163138AAUL; + md->sm3.state[6] = 0xE38DEE4DUL; + md->sm3.state[7] = 0xB0FB0E4EUL; + md->sm3.curlen = 0; + md->sm3.length = 0; + return CRYPT_OK; +} + +/** + Process a block of memory though the hash + @param md The hash state + @param in The data to hash + @param inlen The length of the data (octets) + @return CRYPT_OK if successful +*/ +HASH_PROCESS(sm3_process, s_sm3_compress, sm3, 64) + +/** + Terminate the hash to get the digest + @param md The hash state + @param out [out] The destination of the hash (32 bytes) + @return CRYPT_OK if successful +*/ +int sm3_done(hash_state * md, unsigned char *out) +{ + int i; + + LTC_ARGCHK(md != NULL); + LTC_ARGCHK(out != NULL); + + if (md->sm3.curlen >= sizeof(md->sm3.buf)) { + return CRYPT_INVALID_ARG; + } + + /* increase the length of the message */ + md->sm3.length += md->sm3.curlen * 8; + + /* append the '1' bit */ + md->sm3.buf[md->sm3.curlen++] = (unsigned char)0x80; + + /* if the length is currently above 56 bytes we append zeros + * then compress. Then we can fall back to padding zeros and length + * encoding like normal. + */ + if (md->sm3.curlen > 56) { + while (md->sm3.curlen < 64) { + md->sm3.buf[md->sm3.curlen++] = (unsigned char)0; + } + s_sm3_compress(md, md->sm3.buf); + md->sm3.curlen = 0; + } + + /* pad upto 56 bytes of zeroes */ + while (md->sm3.curlen < 56) { + md->sm3.buf[md->sm3.curlen++] = (unsigned char)0; + } + + /* store length (big-endian) */ + STORE64H(md->sm3.length, md->sm3.buf+56); + s_sm3_compress(md, md->sm3.buf); + + /* copy output (big-endian) */ + for (i = 0; i < 8; i++) { + STORE32H(md->sm3.state[i], out+(4*i)); + } + return CRYPT_OK; +} + +/** + Self-test the hash + @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled +*/ +int sm3_test(void) +{ +#ifndef LTC_TEST + return CRYPT_NOP; +#else + static const struct { + const char *msg; + unsigned char hash[32]; + } tests[] = { + /* Example 1 from the SM3 specification (GM/T 0004-2012) */ + { "abc", + { 0x66, 0xc7, 0xf0, 0xf4, 0x62, 0xee, 0xed, 0xd9, + 0xd1, 0xf2, 0xd4, 0x6b, 0xdc, 0x10, 0xe4, 0xe2, + 0x41, 0x67, 0xc4, 0x87, 0x5c, 0xf2, 0xf7, 0xa2, + 0x29, 0x7d, 0xa0, 0x2b, 0x8f, 0x4b, 0xa8, 0xe0 } + }, + /* Example 2 from the SM3 specification (GM/T 0004-2012) */ + { "abcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcd", + { 0xde, 0xbe, 0x9f, 0xf9, 0x22, 0x75, 0xb8, 0xa1, + 0x38, 0x60, 0x48, 0x89, 0xc1, 0x8e, 0x5a, 0x4d, + 0x6f, 0xdb, 0x70, 0xe5, 0x38, 0x7e, 0x57, 0x65, + 0x29, 0x3d, 0xcb, 0xa3, 0x9c, 0x0c, 0x57, 0x32 } + }, + /* Additional test vectors generated by `openssl dgst -sm3` (OpenSSL 3.0.13) */ + { "", + { 0x1a, 0xb2, 0x1d, 0x83, 0x55, 0xcf, 0xa1, 0x7f, + 0x8e, 0x61, 0x19, 0x48, 0x31, 0xe8, 0x1a, 0x8f, + 0x22, 0xbe, 0xc8, 0xc7, 0x28, 0xfe, 0xfb, 0x74, + 0x7e, 0xd0, 0x35, 0xeb, 0x50, 0x82, 0xaa, 0x2b } + }, + { "a", + { 0x62, 0x34, 0x76, 0xac, 0x18, 0xf6, 0x5a, 0x29, + 0x09, 0xe4, 0x3c, 0x7f, 0xec, 0x61, 0xb4, 0x9c, + 0x7e, 0x76, 0x4a, 0x91, 0xa1, 0x8c, 0xcb, 0x82, + 0xf1, 0x91, 0x7a, 0x29, 0xc8, 0x6c, 0x5e, 0x88 } + }, + { "abcdefghijklmnopqrstuvwxyz", + { 0xb8, 0x0f, 0xe9, 0x7a, 0x4d, 0xa2, 0x4a, 0xfc, + 0x27, 0x75, 0x64, 0xf6, 0x6a, 0x35, 0x9e, 0xf4, + 0x40, 0x46, 0x2a, 0xd2, 0x8d, 0xcc, 0x6d, 0x63, + 0xad, 0xb2, 0x4d, 0x5c, 0x20, 0xa6, 0x15, 0x95 } + }, + { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", + { 0x29, 0x71, 0xd1, 0x0c, 0x88, 0x42, 0xb7, 0x0c, + 0x97, 0x9e, 0x55, 0x06, 0x34, 0x80, 0xc5, 0x0b, + 0xac, 0xff, 0xd9, 0x0e, 0x98, 0xe2, 0xe6, 0x0d, + 0x25, 0x12, 0xab, 0x8a, 0xbf, 0xdf, 0xce, 0xc5 } + }, + { "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + { 0x28, 0x83, 0x37, 0xee, 0xf5, 0x1e, 0xec, 0x62, + 0xe7, 0x54, 0x4d, 0x72, 0x70, 0x42, 0x4c, 0x8d, + 0xbe, 0x65, 0x62, 0x54, 0xc9, 0x98, 0x52, 0x87, + 0x0a, 0x73, 0xb2, 0x45, 0x3a, 0x6a, 0x7f, 0xb1 } + }, + { "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + { 0xba, 0x00, 0xeb, 0xed, 0xaa, 0xb5, 0x40, 0x65, + 0xa5, 0xfd, 0x4f, 0x9f, 0x56, 0x32, 0x60, 0x16, + 0x20, 0x31, 0x66, 0xbc, 0xee, 0x3e, 0xed, 0x44, + 0xea, 0x86, 0x8d, 0x59, 0xd6, 0x7a, 0xa3, 0xc8 } + }, + { "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + { 0x58, 0x73, 0x08, 0x54, 0x35, 0x51, 0x88, 0x1e, + 0xbd, 0x70, 0xd2, 0x7a, 0xd3, 0x58, 0xff, 0x5d, + 0xcd, 0xf2, 0x4a, 0xc5, 0x48, 0x22, 0xe2, 0xf7, + 0xb7, 0xc3, 0xed, 0xce, 0x09, 0x85, 0xd2, 0x1b } + }, + { "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + { 0x61, 0x6e, 0xc4, 0x33, 0xc3, 0x59, 0xe7, 0xc2, + 0xb1, 0x9f, 0x36, 0x0e, 0x2b, 0x8f, 0x2a, 0x1b, + 0x6e, 0x9e, 0xd7, 0x6b, 0x8d, 0xc1, 0xa7, 0xd2, + 0x07, 0xb3, 0x1a, 0x53, 0x41, 0xc6, 0x11, 0xe9 } + } + }; + + int i; + unsigned char tmp[32]; + hash_state md; + + for (i = 0; i < (int)LTC_ARRAY_SIZE(tests); i++) { + sm3_init(&md); + sm3_process(&md, (const unsigned char *)tests[i].msg, XSTRLEN(tests[i].msg)); + sm3_done(&md, tmp); + if (ltc_compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "SM3", i)) { + return CRYPT_FAIL_TESTVECTOR; + } + } + return CRYPT_OK; +#endif +} + +#undef FF0 +#undef GG0 +#undef FF1 +#undef GG1 +#undef R1 +#undef R2 + +#endif diff --git a/src/headers/tomcrypt_custom.h b/src/headers/tomcrypt_custom.h index ed1440082..b34af696a 100644 --- a/src/headers/tomcrypt_custom.h +++ b/src/headers/tomcrypt_custom.h @@ -280,6 +280,7 @@ #define LTC_RIPEMD320 #define LTC_BLAKE2S #define LTC_BLAKE2B +#define LTC_SM3 #define LTC_HASH_HELPERS diff --git a/src/headers/tomcrypt_hash.h b/src/headers/tomcrypt_hash.h index a6bd75028..34dd4e9ab 100644 --- a/src/headers/tomcrypt_hash.h +++ b/src/headers/tomcrypt_hash.h @@ -131,6 +131,14 @@ struct chc_state { }; #endif +#ifdef LTC_SM3 +struct sm3_state { + ulong64 length; + ulong32 state[8], curlen; + unsigned char buf[64]; +}; +#endif + #ifdef LTC_BLAKE2S struct blake2s_state { ulong32 h[8]; @@ -208,6 +216,9 @@ typedef union Hash_state { #ifdef LTC_BLAKE2B struct blake2b_state blake2b; #endif +#ifdef LTC_SM3 + struct sm3_state sm3; +#endif void *data; } hash_state; @@ -488,6 +499,14 @@ int blake2b_process(hash_state * md, const unsigned char *in, unsigned long inle int blake2b_done(hash_state * md, unsigned char *out); #endif +#ifdef LTC_SM3 +int sm3_init(hash_state * md); +int sm3_process(hash_state * md, const unsigned char *in, unsigned long inlen); +int sm3_done(hash_state * md, unsigned char *out); +int sm3_test(void); +extern const struct ltc_hash_descriptor sm3_desc; +#endif + #ifdef LTC_MD5 int md5_init(hash_state * md); int md5_process(hash_state * md, const unsigned char *in, unsigned long inlen); diff --git a/src/mac/hmac/hmac_test.c b/src/mac/hmac/hmac_test.c index f22a37096..762e9bf1a 100644 --- a/src/mac/hmac/hmac_test.c +++ b/src/mac/hmac/hmac_test.c @@ -582,6 +582,40 @@ int hmac_test(void) 0x65, 0xc9, 0x74, 0x40, 0xfa, 0x8c, 0x6a, 0x58} }, #endif /* LTC_TEST_EXT */ + { "sm3 1", "sm3", + hmac_test_case_keys[0], 20, + hmac_test_case_data[0], 8, + {0x51, 0xb0, 0x0d, 0x1f, 0xb4, 0x98, 0x32, 0xbf, + 0xb0, 0x1c, 0x3c, 0xe2, 0x78, 0x48, 0xe5, 0x9f, + 0x87, 0x1d, 0x9b, 0xa9, 0x38, 0xdc, 0x56, 0x3b, + 0x33, 0x8c, 0xa9, 0x64, 0x75, 0x5c, 0xce, 0x70} }, + +#ifdef LTC_TEST_EXT + { "sm3 2", "sm3", + hmac_test_case_keys[1], 4, + hmac_test_case_data[1], 28, + {0x2e, 0x87, 0xf1, 0xd1, 0x68, 0x62, 0xe6, 0xd9, + 0x64, 0xb5, 0x0a, 0x52, 0x00, 0xbf, 0x2b, 0x10, + 0xb7, 0x64, 0xfa, 0xa9, 0x68, 0x0a, 0x29, 0x6a, + 0x24, 0x05, 0xf2, 0x4b, 0xec, 0x39, 0xf8, 0x82} }, + + { "sm3 3", "sm3", + hmac_test_case_keys[4], 131, + hmac_test_case_data[5], 54, + {0x73, 0x6f, 0x6a, 0xbd, 0x55, 0x72, 0xf0, 0xd5, + 0x96, 0xc9, 0x57, 0xb9, 0x30, 0x6b, 0x3c, 0x5c, + 0xe8, 0x13, 0xb2, 0xc4, 0x5c, 0xd7, 0x44, 0x52, + 0xbc, 0x6f, 0xbb, 0x37, 0xd1, 0xed, 0x25, 0xfa} }, + + { "sm3 4", "sm3", + hmac_test_case_keys[4], 131, + hmac_test_case_data[7], 152, + {0x8d, 0x1c, 0xa1, 0xb7, 0x22, 0x53, 0xe7, 0xe9, + 0xc8, 0x22, 0x68, 0x4d, 0x2e, 0x75, 0xfb, 0x6c, + 0x6e, 0x04, 0x42, 0x86, 0x6e, 0x66, 0x1b, 0xb9, + 0xa3, 0x66, 0x8c, 0xd9, 0xc6, 0xa3, 0x2f, 0xb7} }, +#endif /* LTC_TEST_EXT */ + }; unsigned long outlen; diff --git a/src/misc/crypt/crypt.c b/src/misc/crypt/crypt.c index ccef4a0c7..d9ebf16b4 100644 --- a/src/misc/crypt/crypt.c +++ b/src/misc/crypt/crypt.c @@ -220,6 +220,9 @@ const char *crypt_build_settings = #if defined(LTC_BLAKE2B) " BLAKE2B\n" #endif +#if defined(LTC_SM3) + " SM3\n" +#endif #if defined(LTC_CHC_HASH) " CHC_HASH\n" #endif diff --git a/src/misc/crypt/crypt_register_all_hashes.c b/src/misc/crypt/crypt_register_all_hashes.c index 91f1cadb1..620331a84 100644 --- a/src/misc/crypt/crypt_register_all_hashes.c +++ b/src/misc/crypt/crypt_register_all_hashes.c @@ -97,6 +97,9 @@ int register_all_hashes(void) #ifdef LTC_MD4 REGISTER_HASH(&md4_desc); #endif +#ifdef LTC_SM3 + REGISTER_HASH(&sm3_desc); +#endif #ifdef LTC_CHC_HASH { int aes_index = find_cipher_any("aes", 8, 16); diff --git a/tests/test.c b/tests/test.c index 8eb7d7d0b..a88ef0910 100644 --- a/tests/test.c +++ b/tests/test.c @@ -200,6 +200,9 @@ static void s_unregister_all(void) #ifdef LTC_MD4 unregister_hash(&md4_desc); #endif +#ifdef LTC_SM3 + unregister_hash(&sm3_desc); +#endif #ifdef LTC_MD5 unregister_hash(&md5_desc); #endif From ab28d097039ac2ff4029f578306ea77faca7e45b Mon Sep 17 00:00:00 2001 From: Karel Miko Date: Sun, 19 Apr 2026 23:31:11 +0200 Subject: [PATCH 2/9] Update makefiles --- libtomcrypt_VS2008.vcproj | 4 ++++ makefile.mingw | 2 +- makefile.msvc | 2 +- makefile.unix | 2 +- makefile_include.mk | 2 +- sources.cmake | 1 + 6 files changed, 9 insertions(+), 4 deletions(-) diff --git a/libtomcrypt_VS2008.vcproj b/libtomcrypt_VS2008.vcproj index 987f3a33e..27868ef6f 100644 --- a/libtomcrypt_VS2008.vcproj +++ b/libtomcrypt_VS2008.vcproj @@ -903,6 +903,10 @@ RelativePath="src\hashes\sha3_test.c" > + + diff --git a/makefile.mingw b/makefile.mingw index 1d3135eec..1f9c3e013 100644 --- a/makefile.mingw +++ b/makefile.mingw @@ -73,7 +73,7 @@ src/hashes/sha1_desc.o src/hashes/sha1_x86.o src/hashes/sha2/sha224.o src/hashes src/hashes/sha2/sha224_x86.o src/hashes/sha2/sha256.o src/hashes/sha2/sha256_desc.o \ src/hashes/sha2/sha256_x86.o src/hashes/sha2/sha384.o src/hashes/sha2/sha512.o \ src/hashes/sha2/sha512_224.o src/hashes/sha2/sha512_256.o src/hashes/sha3.o src/hashes/sha3_test.o \ -src/hashes/tiger.o src/hashes/whirl/whirl.o src/mac/blake2/blake2bmac.o \ +src/hashes/sm3.o src/hashes/tiger.o src/hashes/whirl/whirl.o src/mac/blake2/blake2bmac.o \ src/mac/blake2/blake2bmac_file.o src/mac/blake2/blake2bmac_memory.o \ src/mac/blake2/blake2bmac_memory_multi.o src/mac/blake2/blake2bmac_test.o src/mac/blake2/blake2smac.o \ src/mac/blake2/blake2smac_file.o src/mac/blake2/blake2smac_memory.o \ diff --git a/makefile.msvc b/makefile.msvc index 5770c4682..5d92f6e4b 100644 --- a/makefile.msvc +++ b/makefile.msvc @@ -66,7 +66,7 @@ src/hashes/sha1_desc.obj src/hashes/sha1_x86.obj src/hashes/sha2/sha224.obj src/ src/hashes/sha2/sha224_x86.obj src/hashes/sha2/sha256.obj src/hashes/sha2/sha256_desc.obj \ src/hashes/sha2/sha256_x86.obj src/hashes/sha2/sha384.obj src/hashes/sha2/sha512.obj \ src/hashes/sha2/sha512_224.obj src/hashes/sha2/sha512_256.obj src/hashes/sha3.obj src/hashes/sha3_test.obj \ -src/hashes/tiger.obj src/hashes/whirl/whirl.obj src/mac/blake2/blake2bmac.obj \ +src/hashes/sm3.obj src/hashes/tiger.obj src/hashes/whirl/whirl.obj src/mac/blake2/blake2bmac.obj \ src/mac/blake2/blake2bmac_file.obj src/mac/blake2/blake2bmac_memory.obj \ src/mac/blake2/blake2bmac_memory_multi.obj src/mac/blake2/blake2bmac_test.obj src/mac/blake2/blake2smac.obj \ src/mac/blake2/blake2smac_file.obj src/mac/blake2/blake2smac_memory.obj \ diff --git a/makefile.unix b/makefile.unix index 5130bef3b..349610ef0 100644 --- a/makefile.unix +++ b/makefile.unix @@ -87,7 +87,7 @@ src/hashes/sha1_desc.o src/hashes/sha1_x86.o src/hashes/sha2/sha224.o src/hashes src/hashes/sha2/sha224_x86.o src/hashes/sha2/sha256.o src/hashes/sha2/sha256_desc.o \ src/hashes/sha2/sha256_x86.o src/hashes/sha2/sha384.o src/hashes/sha2/sha512.o \ src/hashes/sha2/sha512_224.o src/hashes/sha2/sha512_256.o src/hashes/sha3.o src/hashes/sha3_test.o \ -src/hashes/tiger.o src/hashes/whirl/whirl.o src/mac/blake2/blake2bmac.o \ +src/hashes/sm3.o src/hashes/tiger.o src/hashes/whirl/whirl.o src/mac/blake2/blake2bmac.o \ src/mac/blake2/blake2bmac_file.o src/mac/blake2/blake2bmac_memory.o \ src/mac/blake2/blake2bmac_memory_multi.o src/mac/blake2/blake2bmac_test.o src/mac/blake2/blake2smac.o \ src/mac/blake2/blake2smac_file.o src/mac/blake2/blake2smac_memory.o \ diff --git a/makefile_include.mk b/makefile_include.mk index b849f810d..702ff5a1d 100644 --- a/makefile_include.mk +++ b/makefile_include.mk @@ -258,7 +258,7 @@ src/hashes/sha1_desc.o src/hashes/sha1_x86.o src/hashes/sha2/sha224.o src/hashes src/hashes/sha2/sha224_x86.o src/hashes/sha2/sha256.o src/hashes/sha2/sha256_desc.o \ src/hashes/sha2/sha256_x86.o src/hashes/sha2/sha384.o src/hashes/sha2/sha512.o \ src/hashes/sha2/sha512_224.o src/hashes/sha2/sha512_256.o src/hashes/sha3.o src/hashes/sha3_test.o \ -src/hashes/tiger.o src/hashes/whirl/whirl.o src/mac/blake2/blake2bmac.o \ +src/hashes/sm3.o src/hashes/tiger.o src/hashes/whirl/whirl.o src/mac/blake2/blake2bmac.o \ src/mac/blake2/blake2bmac_file.o src/mac/blake2/blake2bmac_memory.o \ src/mac/blake2/blake2bmac_memory_multi.o src/mac/blake2/blake2bmac_test.o src/mac/blake2/blake2smac.o \ src/mac/blake2/blake2smac_file.o src/mac/blake2/blake2smac_memory.o \ diff --git a/sources.cmake b/sources.cmake index 38c5d9b25..82383087d 100644 --- a/sources.cmake +++ b/sources.cmake @@ -115,6 +115,7 @@ src/hashes/sha2/sha512_224.c src/hashes/sha2/sha512_256.c src/hashes/sha3.c src/hashes/sha3_test.c +src/hashes/sm3.c src/hashes/tiger.c src/hashes/whirl/whirl.c src/hashes/whirl/whirltab.c From 1fff1ea5d23410d6c3449c1e320a9e97466824bc Mon Sep 17 00:00:00 2001 From: Karel Miko Date: Sun, 19 Apr 2026 23:58:38 +0200 Subject: [PATCH 3/9] add sm3 to hashsum_tv.txt --- notes/hashsum_tv.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/notes/hashsum_tv.txt b/notes/hashsum_tv.txt index 2bf53d300..4f9654147 100644 --- a/notes/hashsum_tv.txt +++ b/notes/hashsum_tv.txt @@ -29,6 +29,7 @@ sha384: 7cc080c662524617e56d5a49f1c185909e9b1858a86684161ddd97fc5426f693b53f59d7 sha512: f90afe4d254716a9770fd2c4f29ca544f2975f961cbd7fa207117383e4e48f7a2e1ade4aac333a2cb8c227dd6af2fff4d87c31c2a3916ae24d507c7c94c21818 *tests/test.key sha512-224: 64ec566b5c2de736eab1b4e8542dc110f736819ea7f8f48e3712fbad *tests/test.key sha512-256: db880bce4beb7246510febb961c7595aab57a15de6f90cd079f145e476b5d773 *tests/test.key +sm3: e03629750a6e6be2b1be1dde48b83be44a7ff19f1cbe3d9bcab540aa2b7e4d6c *tests/test.key tiger: 97d713850e7affac30a642572c1ee7b18793d5b9e0ef5932 *tests/test.key tiger2: b2dfd53b3edba5b54e1f21a82cbf6a3475efbce33a8cae03 *tests/test.key whirlpool: d7d41c755e0f28313f254cb198e0bfa42f56670595d97b80dceec754825d69938a9c11e5bf16e9a3809a62a09bddf021f3dbff4302ceec7ba46c88b41772b711 *tests/test.key From f89ca256b5aace3a67b4f4237729bf2dd0d29b3e Mon Sep 17 00:00:00 2001 From: Karel Miko Date: Tue, 21 Apr 2026 20:56:29 +0200 Subject: [PATCH 4/9] SM2 --- doc/crypt.tex | 75 ++ src/headers/tomcrypt_custom.h | 1 + src/headers/tomcrypt_pk.h | 20 + src/headers/tomcrypt_private.h | 1 + src/pk/asn1/oid/pk_get.c | 1 + src/pk/ecc/ecc.c | 13 +- src/pk/ecc/ecc_find_curve.c | 5 + src/pk/ecc/ecc_sm2.c | 737 ++++++++++++++++++ tests/ecc_sm2_test.c | 273 +++++++ tests/ecc_test.c | 3 + tests/pem/openssl_sm2_pk.pem | 4 + tests/pem/openssl_sm2_sk.pem | 5 + tests/pem/openssl_sm2_sk_pw.pem | 7 + tests/pem/openssl_sm2_sk_pw_t.pem | 8 + tests/pem/openssl_sm2_sk_t.pem | 5 + tests/pem/openssl_sm2_x509.pem | 11 + tests/pem/pkcs/sm2-pkcs8/openssl_sm2_sk.pk8 | 5 + .../pkcs/sm2-pkcs8/openssl_sm2_sk_pbes1.pk8 | 6 + .../pkcs/sm2-pkcs8/openssl_sm2_sk_pbes2.pk8 | 7 + tests/pem_test.c | 44 ++ tests/test.c | 1 + tests/tomcrypt_test.h | 1 + 22 files changed, 1232 insertions(+), 1 deletion(-) create mode 100644 src/pk/ecc/ecc_sm2.c create mode 100644 tests/ecc_sm2_test.c create mode 100644 tests/pem/openssl_sm2_pk.pem create mode 100644 tests/pem/openssl_sm2_sk.pem create mode 100644 tests/pem/openssl_sm2_sk_pw.pem create mode 100644 tests/pem/openssl_sm2_sk_pw_t.pem create mode 100644 tests/pem/openssl_sm2_sk_t.pem create mode 100644 tests/pem/openssl_sm2_x509.pem create mode 100644 tests/pem/pkcs/sm2-pkcs8/openssl_sm2_sk.pk8 create mode 100644 tests/pem/pkcs/sm2-pkcs8/openssl_sm2_sk_pbes1.pk8 create mode 100644 tests/pem/pkcs/sm2-pkcs8/openssl_sm2_sk_pbes2.pk8 diff --git a/doc/crypt.tex b/doc/crypt.tex index 622e7ee12..4c30a234d 100644 --- a/doc/crypt.tex +++ b/doc/crypt.tex @@ -5279,6 +5279,7 @@ \chapter{Elliptic Curve Cryptography - $GF(p)$} \hline \texttt{secp224k1} & & 1.3.132.0.32 \\ \hline \texttt{secp256r1} & nistp256, prime256v1, ECC-256, P-256 & 1.2.840.10045.3.1.7 \\ \hline \texttt{secp256k1} & & 1.3.132.0.10 \\ +\hline \texttt{sm2p256v1} & SM2P256V1, SM2 & 1.2.156.10197.1.301 \\ \hline \texttt{secp384r1} & nistp384, ECC-384, P-384 & 1.3.132.0.34 \\ \hline \texttt{secp521r1} & nistp521, ECC-521, P-521 & 1.3.132.0.35 \\ \hline \texttt{prime239v1} & & 1.2.840.10045.3.1.4 \\ @@ -5909,6 +5910,47 @@ \subsection{Signature Formats} the option to use \code{LTC\_ECCSIG\_ANSIX962}. Also it is possible to disable \code{LTC\_SSH} which will disable the option to use \code{LTC\_ECCSIG\_RFC5656}. +\mysection{Signatures (SM2)} +The library also provides helpers for the \textit{SM2} signature scheme. In contrast to the hash-level \textit{ECDSA} API, +these functions operate on the original message and the signer identifier (application-defined user ID bound into ZA). Internally they compute the SM2 message digest +\textit{Hash(ZA || M)}, where \textit{ZA} is the SM2 digest of the signer identifier, curve parameters, and public key, and produce or verify a DER-encoded \textit{(r, s)} signature. Standard deployments typically use +the built-in curve \texttt{sm2p256v1} together with the \textit{SM3} hash. These SM2 functions accept only keys on the built-in +\texttt{sm2p256v1} curve. + +\textbf{NOTE:} These functions require \code{LTC\_DER}. + +\subsection{Signature Generation} +\index{ecc\_sign\_sm2()} +\begin{verbatim} +int ecc_sign_sm2(const unsigned char *id, unsigned long idlen, + const unsigned char *msg, unsigned long msglen, + unsigned char *out, unsigned long *outlen, + prng_state *prng, int wprng, int hash_idx, + const ecc_key *key); +\end{verbatim} + +This function signs the message in \code{msg} of length \code{msglen} octets using the signer identifier (application-defined user ID bound into ZA) \code{id} of +length \code{idlen} octets. The resulting DER-encoded signature is stored in \code{out}. The \code{hash\_idx} parameter +selects the hash used for both \code{ZA} and the message digest. If \code{hash\_idx} is \code{-1}, the default \textit{SM3} +hash is used. Other hashes are supported for compatibility and testing, but should only rarely be used in practice. The +\code{key} must be a private ECC key on the built-in \texttt{sm2p256v1} curve. + +\subsection{Signature Verification} +\index{ecc\_verify\_sm2()} +\begin{verbatim} +int ecc_verify_sm2(const unsigned char *id, unsigned long idlen, + const unsigned char *msg, unsigned long msglen, + const unsigned char *sig, unsigned long siglen, + int hash_idx, int *stat, const ecc_key *key); +\end{verbatim} + +This function verifies the DER-encoded signature in \code{sig} against the message in \code{msg} and the signer identifier +(application-defined user ID bound into ZA) \code{id}. The same identifier and hash must be used as during signature generation. The result is stored in \code{stat}, +which is set to a non-zero value if the signature is valid. If \code{hash\_idx} is \code{-1}, the default \textit{SM3} +hash is used. Other hashes are supported for compatibility and testing, but should only rarely be used in practice. The +\code{key} must contain the corresponding public key (or the private key matching that public key) on the built-in +\texttt{sm2p256v1} curve. + \mysection{Shared Secret (ECDH)} To construct a Diffie-Hellman shared secret with a private and public ECC key, use the following function: \index{ecc\_shared\_secret()} @@ -5974,6 +6016,39 @@ \subsection{Encryption Format} } \end{verbatim} +\mysection{Encrypt and Decrypt (SM2)} +The library also provides \textit{SM2} public-key encryption. The interface uses the raw SM2 ciphertext layout +\code{C1 || C3 || C2}, not the ASN.1 wrapper used by \code{ecc\_encrypt\_key()}. These SM2 functions accept only keys on the +built-in \texttt{sm2p256v1} curve. + +\subsection{Encryption} +\index{ecc\_encrypt\_key\_sm2()} +\begin{verbatim} +int ecc_encrypt_key_sm2(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen, + prng_state *prng, int wprng, int hash_idx, + const ecc_key *key); +\end{verbatim} + +This function encrypts the plaintext in \code{in} using the recipient public key in \code{key}. The \code{hash\_idx} +parameter selects the hash used by the SM2 KDF and for computing \code{C3}. If \code{hash\_idx} is \code{-1}, the default +\textit{SM3} hash is used. Other hashes are supported for compatibility and testing, but should only rarely be used in +practice. The ciphertext is written to \code{out} in \code{C1 || C3 || C2} format, where \code{C1} is the ephemeral public +point, \code{C3} is the authentication hash, and \code{C2} is the masked plaintext. + +\subsection{Decryption} +\index{ecc\_decrypt\_key\_sm2()} +\begin{verbatim} +int ecc_decrypt_key_sm2(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen, + int hash_idx, const ecc_key *key); +\end{verbatim} + +This function decrypts an SM2 ciphertext in \code{C1 || C3 || C2} format using the recipient private key in \code{key}. +The \code{hash\_idx} parameter must match the hash used during encryption. If \code{hash\_idx} is \code{-1}, the default +\textit{SM3} hash is used. Other hashes are supported for compatibility and testing, but should only rarely be used in +practice. The function verifies \code{C3} before returning the recovered plaintext in \code{out}. + \chapter{Elliptic Curve Cryptography - $Montgomery/Twisted Edwards$} \mysection{Introduction} diff --git a/src/headers/tomcrypt_custom.h b/src/headers/tomcrypt_custom.h index b34af696a..7393977c5 100644 --- a/src/headers/tomcrypt_custom.h +++ b/src/headers/tomcrypt_custom.h @@ -576,6 +576,7 @@ #define LTC_ECC_SECP224K1 #define LTC_ECC_SECP224R1 #define LTC_ECC_SECP256K1 + #define LTC_ECC_SM2P256V1 #define LTC_ECC_SECP256R1 #define LTC_ECC_SECP384R1 #define LTC_ECC_SECP521R1 diff --git a/src/headers/tomcrypt_pk.h b/src/headers/tomcrypt_pk.h index 5fee1a2ba..64957177b 100644 --- a/src/headers/tomcrypt_pk.h +++ b/src/headers/tomcrypt_pk.h @@ -468,11 +468,31 @@ int ecc_encrypt_key(const unsigned char *in, unsigned long inlen, prng_state *prng, int wprng, int hash, const ecc_key *key); +int ecc_sign_sm2(const unsigned char *id, unsigned long idlen, + const unsigned char *msg, unsigned long msglen, + unsigned char *out, unsigned long *outlen, + prng_state *prng, int wprng, int hash_idx, + const ecc_key *key); + +int ecc_verify_sm2(const unsigned char *id, unsigned long idlen, + const unsigned char *msg, unsigned long msglen, + const unsigned char *sig, unsigned long siglen, + int hash_idx, int *stat, const ecc_key *key); + int ecc_decrypt_key(const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen, const ecc_key *key); #endif /* LTC_DER */ +int ecc_encrypt_key_sm2(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen, + prng_state *prng, int wprng, int hash_idx, + const ecc_key *key); + +int ecc_decrypt_key_sm2(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen, + int hash_idx, const ecc_key *key); + #define ltc_ecc_sign_hash(i, il, o, ol, p, wp, k) \ ecc_sign_hash_v2(i, il, o, ol, \ &(ltc_ecc_sig_opts){ \ diff --git a/src/headers/tomcrypt_private.h b/src/headers/tomcrypt_private.h index 1658cca7a..3827e5dd9 100644 --- a/src/headers/tomcrypt_private.h +++ b/src/headers/tomcrypt_private.h @@ -57,6 +57,7 @@ enum ltc_oid_id { LTC_OID_DSA, LTC_OID_EC, LTC_OID_EC_PRIMEF, + LTC_OID_SM2SIG_SM3, LTC_OID_X25519, LTC_OID_ED25519, LTC_OID_DH, diff --git a/src/pk/asn1/oid/pk_get.c b/src/pk/asn1/oid/pk_get.c index 81a1b2f3e..815c3a090 100644 --- a/src/pk/asn1/oid/pk_get.c +++ b/src/pk/asn1/oid/pk_get.c @@ -17,6 +17,7 @@ static const oid_table_entry pka_oids[] = { { LTC_OID_DSA, LTC_PKA_DSA, NULL, "1.2.840.10040.4.1" }, { LTC_OID_EC, LTC_PKA_EC, NULL, "1.2.840.10045.2.1" }, { LTC_OID_EC_PRIMEF, LTC_PKA_EC, NULL, "1.2.840.10045.1.1" }, + { LTC_OID_SM2SIG_SM3, LTC_PKA_EC, "sm3", "1.2.156.10197.1.501" }, { LTC_OID_X25519, LTC_PKA_X25519, NULL, "1.3.101.110" }, { LTC_OID_ED25519, LTC_PKA_ED25519, NULL, "1.3.101.112" }, { LTC_OID_DH, LTC_PKA_DH, NULL, "1.2.840.113549.1.3.1" }, diff --git a/src/pk/ecc/ecc.c b/src/pk/ecc/ecc.c index 84068a978..834e47b7e 100644 --- a/src/pk/ecc/ecc.c +++ b/src/pk/ecc/ecc.c @@ -198,6 +198,18 @@ const ltc_ecc_curve ltc_ecc_curves[] = { /* OID */ "1.3.132.0.10" }, #endif +#ifdef LTC_ECC_SM2P256V1 +{ + /* prime */ "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF", + /* A */ "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC", + /* B */ "28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93", + /* order */ "FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123", + /* Gx */ "32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7", + /* Gy */ "BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0", + /* cofactor */ 1, + /* OID */ "1.2.156.10197.1.301" +}, +#endif #ifdef LTC_ECC_SECP384R1 { /* prime */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF", @@ -432,4 +444,3 @@ const ltc_ecc_curve ltc_ecc_curves[] = { }; #endif - diff --git a/src/pk/ecc/ecc_find_curve.c b/src/pk/ecc/ecc_find_curve.c index 7942d130f..96c6e22e7 100644 --- a/src/pk/ecc/ecc_find_curve.c +++ b/src/pk/ecc/ecc_find_curve.c @@ -84,6 +84,11 @@ static const struct { "1.3.132.0.10", { "SECP256K1", NULL } }, #endif +#ifdef LTC_ECC_SM2P256V1 + { + "1.2.156.10197.1.301", { "SM2P256V1", "SM2", NULL } + }, +#endif #ifdef LTC_ECC_SECP384R1 { "1.3.132.0.34", { "SECP384R1", "NISTP384", "ECC-384", "P-384", NULL } diff --git a/src/pk/ecc/ecc_sm2.c b/src/pk/ecc/ecc_sm2.c new file mode 100644 index 000000000..761a811a3 --- /dev/null +++ b/src/pk/ecc/ecc_sm2.c @@ -0,0 +1,737 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ + +#include "tomcrypt_private.h" + +/** + @file ecc_sm2.c + SM2 helpers built on top of the existing ECC implementation +*/ + +#ifdef LTC_MECC + +static int s_sm2_hash_idx(int hash_idx) +{ + if (hash_idx == -1) hash_idx = find_hash("sm3"); + return hash_idx >= 0 ? hash_idx : CRYPT_INVALID_HASH; +} + +static int s_sm2_only_curve(const ecc_key *key) +{ + const ltc_ecc_curve *curve; + unsigned long oid[16], oidlen = 16; + int err; + + LTC_ARGCHK(key != NULL); + + if ((err = ecc_find_curve("SM2", &curve)) != CRYPT_OK) return err; + if (curve->OID == NULL) return CRYPT_INVALID_ARG; + if (key->dp.oidlen == 0) return CRYPT_INVALID_ARG; + if ((err = pk_oid_str_to_num(curve->OID, oid, &oidlen)) != CRYPT_OK) return err; + if (key->dp.oidlen != oidlen) return CRYPT_INVALID_ARG; + if (XMEM_NEQ(key->dp.oid, oid, oidlen * sizeof(oid[0])) != 0) return CRYPT_INVALID_ARG; + return CRYPT_OK; +} + +static int s_sm2_export_fixed(void *num, unsigned long size, unsigned char *out) +{ + unsigned long used; + + LTC_ARGCHK(num != NULL); + LTC_ARGCHK(out != NULL); + + if (size > ECC_BUF_SIZE) return CRYPT_BUFFER_OVERFLOW; + used = ltc_mp_unsigned_bin_size(num); + if (used > size) return CRYPT_BUFFER_OVERFLOW; + zeromem(out, size); + return ltc_mp_to_unsigned_bin(num, out + (size - used)); +} + +static int s_sm2_hash_to_e(const unsigned char *in, unsigned long inlen, const ecc_key *key, void *e) +{ + int err; + unsigned long pbits, pbytes, i, shift_right; + unsigned char ch, buf[MAXBLOCKSIZE]; + void *p; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(key != NULL); + LTC_ARGCHK(e != NULL); + + p = key->dp.order; + pbits = ltc_mp_count_bits(p); + pbytes = (pbits + 7uL) >> 3; + + if (pbits > inlen * 8uL) return ltc_mp_read_unsigned_bin(e, in, inlen); + if ((pbits % 8uL) == 0uL) return ltc_mp_read_unsigned_bin(e, in, pbytes); + if (pbytes >= MAXBLOCKSIZE) return CRYPT_BUFFER_OVERFLOW; + + shift_right = 8uL - (pbits % 8uL); + for (i = 0, ch = 0; i < pbytes; i++) { + buf[i] = ch; + ch = (unsigned char)(in[i] << (8uL - shift_right)); + buf[i] ^= (unsigned char)(in[i] >> shift_right); + } + + err = ltc_mp_read_unsigned_bin(e, buf, pbytes); +#ifdef LTC_CLEAN_STACK + zeromem(buf, sizeof(buf)); +#endif + return err; +} + +static int s_sm2_is_all_zero(const unsigned char *buf, unsigned long len) +{ + unsigned char acc = 0; + while (len-- > 0uL) acc |= *buf++; + return acc == 0; +} + +static int s_sm2_kdf(int hash_idx, const unsigned char *z, unsigned long zlen, unsigned char *out, unsigned long outlen) +{ + hash_state md; + unsigned char *digest; + unsigned long copied, hashsize, take; + ulong32 counter; + int err; + + LTC_ARGCHK(z != NULL); + LTC_ARGCHK(out != NULL || outlen == 0uL); + + if (outlen == 0uL) return CRYPT_OK; + + if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) return err; + + hashsize = hash_descriptor[hash_idx].hashsize; + digest = XMALLOC(hashsize); + if (digest == NULL) { + return CRYPT_MEM; + } + + err = CRYPT_OK; + copied = 0; + counter = 1; + while (copied < outlen) { + unsigned char ctr[4]; + + ctr[0] = (unsigned char)((counter >> 24) & 255); + ctr[1] = (unsigned char)((counter >> 16) & 255); + ctr[2] = (unsigned char)((counter >> 8) & 255); + ctr[3] = (unsigned char)(counter & 255); + + if ((err = hash_descriptor[hash_idx].init(&md)) != CRYPT_OK) goto cleanup; + if ((err = hash_descriptor[hash_idx].process(&md, z, zlen)) != CRYPT_OK) goto cleanup; + if ((err = hash_descriptor[hash_idx].process(&md, ctr, sizeof(ctr))) != CRYPT_OK) goto cleanup; + if ((err = hash_descriptor[hash_idx].done(&md, digest)) != CRYPT_OK) goto cleanup; + + take = MIN(hashsize, outlen - copied); + XMEMCPY(out + copied, digest, take); + copied += take; + + counter++; + if (copied < outlen && counter == 0uL) { + err = CRYPT_OVERFLOW; + goto cleanup; + } + } + +cleanup: +#ifdef LTC_CLEAN_STACK + zeromem(&md, sizeof(md)); + zeromem(digest, hashsize); +#endif + XFREE(digest); + return err; +} + +static int s_sm2_shared_xy(const ecc_key *private_key, const ecc_key *public_key, unsigned char *out) +{ + ecc_point *result; + int err; + + LTC_ARGCHK(private_key != NULL); + LTC_ARGCHK(public_key != NULL); + LTC_ARGCHK(out != NULL); + + result = ltc_ecc_new_point(); + if (result == NULL) return CRYPT_MEM; + + err = ltc_mp.ecc_ptmul(private_key->k, &public_key->pubkey, result, private_key->dp.A, private_key->dp.prime, 1); + if (err == CRYPT_OK) { + err = s_sm2_export_fixed(result->x, private_key->dp.size, out); + } + if (err == CRYPT_OK) { + err = s_sm2_export_fixed(result->y, private_key->dp.size, out + private_key->dp.size); + } + ltc_ecc_del_point(result); + return err; +} + +static int s_ecc_compute_z_sm2(unsigned char *out, unsigned long *outlen, + const unsigned char *id, unsigned long idlen, + int hash_idx, const ecc_key *key) +{ + hash_state md; + unsigned char entl[2]; + unsigned char buf[ECC_BUF_SIZE]; + unsigned long bits; + int err; + + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + LTC_ARGCHK(id != NULL); + LTC_ARGCHK(key != NULL); + + if (key->type != PK_PUBLIC && key->type != PK_PRIVATE) return CRYPT_PK_INVALID_TYPE; + if ((err = s_sm2_only_curve(key)) != CRYPT_OK) return err; + if ((hash_idx = s_sm2_hash_idx(hash_idx)) < 0) return hash_idx; + if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) return err; + + if (key->dp.size < 0 || (unsigned long)key->dp.size > sizeof(buf)) return CRYPT_BUFFER_OVERFLOW; + + LTC_ARGCHK(idlen <= 8191uL); + + if (*outlen < hash_descriptor[hash_idx].hashsize) { + *outlen = hash_descriptor[hash_idx].hashsize; + return CRYPT_BUFFER_OVERFLOW; + } + + bits = idlen * 8uL; + entl[0] = (unsigned char)((bits >> 8) & 255); + entl[1] = (unsigned char)(bits & 255); + + /* ZA = H(ENTL || ID || a || b || xG || yG || xA || yA) */ + if ((err = hash_descriptor[hash_idx].init(&md)) != CRYPT_OK) goto cleanup; + if ((err = hash_descriptor[hash_idx].process(&md, entl, sizeof(entl))) != CRYPT_OK) goto cleanup; + if (idlen > 0uL) { + if ((err = hash_descriptor[hash_idx].process(&md, id, idlen)) != CRYPT_OK) goto cleanup; + } + if ((err = s_sm2_export_fixed(key->dp.A, key->dp.size, buf)) != CRYPT_OK) goto cleanup; + if ((err = hash_descriptor[hash_idx].process(&md, buf, key->dp.size)) != CRYPT_OK) goto cleanup; + if ((err = s_sm2_export_fixed(key->dp.B, key->dp.size, buf)) != CRYPT_OK) goto cleanup; + if ((err = hash_descriptor[hash_idx].process(&md, buf, key->dp.size)) != CRYPT_OK) goto cleanup; + if ((err = s_sm2_export_fixed(key->dp.base.x, key->dp.size, buf)) != CRYPT_OK) goto cleanup; + if ((err = hash_descriptor[hash_idx].process(&md, buf, key->dp.size)) != CRYPT_OK) goto cleanup; + if ((err = s_sm2_export_fixed(key->dp.base.y, key->dp.size, buf)) != CRYPT_OK) goto cleanup; + if ((err = hash_descriptor[hash_idx].process(&md, buf, key->dp.size)) != CRYPT_OK) goto cleanup; + if ((err = s_sm2_export_fixed(key->pubkey.x, key->dp.size, buf)) != CRYPT_OK) goto cleanup; + if ((err = hash_descriptor[hash_idx].process(&md, buf, key->dp.size)) != CRYPT_OK) goto cleanup; + if ((err = s_sm2_export_fixed(key->pubkey.y, key->dp.size, buf)) != CRYPT_OK) goto cleanup; + if ((err = hash_descriptor[hash_idx].process(&md, buf, key->dp.size)) != CRYPT_OK) goto cleanup; + if ((err = hash_descriptor[hash_idx].done(&md, out)) != CRYPT_OK) goto cleanup; + *outlen = hash_descriptor[hash_idx].hashsize; + +cleanup: +#ifdef LTC_CLEAN_STACK + zeromem(&md, sizeof(md)); + zeromem(buf, sizeof(buf)); +#endif + return err; +} + +#if defined(LTC_DER) +static int s_sm2_digest_message(unsigned char *out, unsigned long *outlen, + const unsigned char *id, unsigned long idlen, + const unsigned char *msg, unsigned long msglen, + int hash_idx, const ecc_key *key) +{ + hash_state md; + unsigned char za[MAXBLOCKSIZE]; + unsigned long hashsize, zalen; + int err; + + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + LTC_ARGCHK(id != NULL); + LTC_ARGCHK(msg != NULL); + LTC_ARGCHK(key != NULL); + + if ((hash_idx = s_sm2_hash_idx(hash_idx)) < 0) return hash_idx; + if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) return err; + + hashsize = hash_descriptor[hash_idx].hashsize; + if (hashsize > sizeof(za)) return CRYPT_BUFFER_OVERFLOW; + if (*outlen < hashsize) { + *outlen = hashsize; + return CRYPT_BUFFER_OVERFLOW; + } + + zalen = hashsize; + if ((err = s_ecc_compute_z_sm2(za, &zalen, id, idlen, hash_idx, key)) != CRYPT_OK) return err; + /* e = H(ZA || msg) */ + if ((err = hash_descriptor[hash_idx].init(&md)) != CRYPT_OK) goto cleanup; + if ((err = hash_descriptor[hash_idx].process(&md, za, zalen)) != CRYPT_OK) goto cleanup; + if (msglen > 0uL) { + if ((err = hash_descriptor[hash_idx].process(&md, msg, msglen)) != CRYPT_OK) goto cleanup; + } + if ((err = hash_descriptor[hash_idx].done(&md, out)) != CRYPT_OK) goto cleanup; + *outlen = hashsize; + +cleanup: +#ifdef LTC_CLEAN_STACK + zeromem(&md, sizeof(md)); + zeromem(za, sizeof(za)); +#endif + return err; +} + +static int s_ecc_sign_hash_sm2(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen, + prng_state *prng, int wprng, const ecc_key *key) +{ + ecc_key pubkey; + void *r, *s, *e, *b, *one_plus_d, *tmp; + int err, have_pubkey = 0, max_iterations; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + LTC_ARGCHK(key != NULL); + + if (key->type != PK_PRIVATE) return CRYPT_PK_NOT_PRIVATE; + + if ((err = ltc_mp_init_multi(&r, &s, &e, &b, &one_plus_d, &tmp, LTC_NULL)) != CRYPT_OK) return err; + + if ((err = s_sm2_hash_to_e(in, inlen, key, e)) != CRYPT_OK) goto cleanup; + if ((err = ltc_mp_add_d(key->k, 1, one_plus_d)) != CRYPT_OK) goto cleanup; + if (ltc_mp_cmp(one_plus_d, key->dp.order) != LTC_MP_LT) { + err = CRYPT_INVALID_ARG; + goto cleanup; + } + + /* r = (e + x1) mod n + s = modinv(1+dA) * (k - r*dA) mod n + modular inverse is blinded with random b + */ + + err = CRYPT_ERROR; + have_pubkey = 0; + for (max_iterations = LTC_PK_MAX_RETRIES; max_iterations > 0; max_iterations--) { + if ((err = ecc_copy_curve(key, &pubkey)) != CRYPT_OK) goto cleanup; + have_pubkey = 1; + if ((err = ecc_generate_key(prng, wprng, &pubkey)) != CRYPT_OK) goto cleanup; + if ((err = ltc_mp_add(e, pubkey.pubkey.x, r)) != CRYPT_OK) goto cleanup; + if ((err = ltc_mp_mod(r, key->dp.order, r)) != CRYPT_OK) goto cleanup; + if (ltc_mp_iszero(r) == LTC_MP_YES) { + ecc_free(&pubkey); + have_pubkey = 0; + continue; + } + if ((err = ltc_mp_add(r, pubkey.k, tmp)) != CRYPT_OK) goto cleanup; + if (ltc_mp_cmp(tmp, key->dp.order) == LTC_MP_EQ) { + ecc_free(&pubkey); + have_pubkey = 0; + continue; + } + if ((err = rand_bn_upto(b, key->dp.order, prng, wprng)) != CRYPT_OK) goto cleanup; + if ((err = ltc_mp_mulmod(key->k, r, key->dp.order, s)) != CRYPT_OK) goto cleanup; + if ((err = ltc_mp_submod(pubkey.k, s, key->dp.order, s)) != CRYPT_OK) goto cleanup; + if ((err = ltc_mp_mulmod(one_plus_d, b, key->dp.order, tmp)) != CRYPT_OK) goto cleanup; + if ((err = ltc_mp_invmod(tmp, key->dp.order, tmp)) != CRYPT_OK) goto cleanup; + if ((err = ltc_mp_mulmod(s, b, key->dp.order, s)) != CRYPT_OK) goto cleanup; + if ((err = ltc_mp_mulmod(s, tmp, key->dp.order, s)) != CRYPT_OK) goto cleanup; + ecc_free(&pubkey); + have_pubkey = 0; + if (ltc_mp_iszero(s) == LTC_MP_NO) { + err = der_encode_sequence_multi(out, outlen, LTC_ASN1_INTEGER, 1uL, r, LTC_ASN1_INTEGER, 1uL, s, LTC_ASN1_EOL, 0uL, NULL); + goto cleanup; + } + } + err = CRYPT_ERROR; + +cleanup: + if (have_pubkey) ecc_free(&pubkey); + ltc_mp_deinit_multi(r, s, e, b, one_plus_d, tmp, LTC_NULL); + return err; +} + +/** + Sign a message with SM2 + @param id The signer identifier used to compute ZA + @param idlen The length of the signer identifier in octets + @param msg The message to sign + @param msglen The length of the message in octets + @param out [out] The destination for the DER-encoded signature + @param outlen [in/out] The max size and resulting size of the signature + @param prng An active PRNG state + @param wprng The index of the PRNG to use + @param hash_idx The index of the hash to use for ZA and message digesting, or -1 to use the default SM3 hash + @param key The private ECC key to sign with; it must use the built-in sm2p256v1 curve + @return CRYPT_OK if successful + @note The default hash is SM3. Other hashes should only rarely be used in practice. +*/ +int ecc_sign_sm2(const unsigned char *id, unsigned long idlen, + const unsigned char *msg, unsigned long msglen, + unsigned char *out, unsigned long *outlen, + prng_state *prng, int wprng, + int hash_idx, const ecc_key *key) +{ + unsigned char digest[MAXBLOCKSIZE]; + unsigned long digestlen = sizeof(digest); + int err; + + LTC_ARGCHK(id != NULL); + LTC_ARGCHK(msg != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + LTC_ARGCHK(key != NULL); + + if ((err = s_sm2_only_curve(key)) != CRYPT_OK) return err; + if ((err = s_sm2_digest_message(digest, &digestlen, id, idlen, msg, msglen, hash_idx, key)) != CRYPT_OK) return err; + return s_ecc_sign_hash_sm2(digest, digestlen, out, outlen, prng, wprng, key); +} + +static int s_ecc_verify_hash_sm2(const unsigned char *sig, unsigned long siglen, + const unsigned char *hash, unsigned long hashlen, + int *stat, const ecc_key *key) +{ + ecc_point *mG = NULL, *mQ = NULL; + void *r, *s, *t, *e, *R, *a_plus3; + void *mu = NULL, *ma = NULL; + void *mp = NULL; + int err; + + LTC_ARGCHK(sig != NULL); + LTC_ARGCHK(hash != NULL); + LTC_ARGCHK(stat != NULL); + LTC_ARGCHK(key != NULL); + + if (key->type != PK_PUBLIC && key->type != PK_PRIVATE) return CRYPT_PK_INVALID_TYPE; + + *stat = 0; + + if ((err = ltc_mp_init_multi(&r, &s, &t, &e, &R, &a_plus3, LTC_NULL)) != CRYPT_OK) return err; + + if ((err = der_decode_sequence_multi_ex(sig, siglen, + LTC_DER_SEQ_SEQUENCE | LTC_DER_SEQ_STRICT, + LTC_ASN1_INTEGER, 1uL, r, + LTC_ASN1_INTEGER, 1uL, s, + LTC_ASN1_EOL, 0uL, LTC_NULL)) != CRYPT_OK) goto cleanup; + + if (ltc_mp_cmp_d(r, 0) != LTC_MP_GT || ltc_mp_cmp_d(s, 0) != LTC_MP_GT || + ltc_mp_cmp(r, key->dp.order) != LTC_MP_LT || ltc_mp_cmp(s, key->dp.order) != LTC_MP_LT) { + err = CRYPT_INVALID_PACKET; + goto cleanup; + } + + /* t = r + s mod n + mG = scalmult(s, G) + scalmult(t, pubkey) + R = (e + mG.x) mod n + accept only if R == r + */ + + if ((err = s_sm2_hash_to_e(hash, hashlen, key, e)) != CRYPT_OK) goto cleanup; + if ((err = ltc_mp_add(r, s, t)) != CRYPT_OK) goto cleanup; + if ((err = ltc_mp_mod(t, key->dp.order, t)) != CRYPT_OK) goto cleanup; + if (ltc_mp_iszero(t) == LTC_MP_YES) { + err = CRYPT_OK; + goto cleanup; + } + + if ((err = ltc_mp_add_d(key->dp.A, 3, a_plus3)) != CRYPT_OK) goto cleanup; + + mG = ltc_ecc_new_point(); + mQ = ltc_ecc_new_point(); + if (mG == NULL || mQ == NULL) { + err = CRYPT_MEM; + goto cleanup; + } + + if ((err = ltc_ecc_copy_point(&key->dp.base, mG)) != CRYPT_OK) goto cleanup; + if ((err = ltc_ecc_copy_point(&key->pubkey, mQ)) != CRYPT_OK) goto cleanup; + if ((err = ltc_mp_montgomery_setup(key->dp.prime, &mp)) != CRYPT_OK) goto cleanup; + if (ltc_mp_cmp(a_plus3, key->dp.prime) != LTC_MP_EQ) { + if ((err = ltc_mp_init_multi(&mu, &ma, LTC_NULL)) != CRYPT_OK) goto cleanup; + if ((err = ltc_mp_montgomery_normalization(mu, key->dp.prime)) != CRYPT_OK) goto cleanup; + if ((err = ltc_mp_mulmod(key->dp.A, mu, key->dp.prime, ma)) != CRYPT_OK) goto cleanup; + } + if (ltc_mp.ecc_mul2add == NULL) { + if ((err = ltc_mp.ecc_ptmul(s, mG, mG, key->dp.A, key->dp.prime, 0)) != CRYPT_OK) goto cleanup; + if ((err = ltc_mp.ecc_ptmul(t, mQ, mQ, key->dp.A, key->dp.prime, 0)) != CRYPT_OK) goto cleanup; + if ((err = ltc_mp.ecc_ptadd(mQ, mG, mG, ma, key->dp.prime, mp)) != CRYPT_OK) goto cleanup; + if ((err = ltc_mp.ecc_map(mG, key->dp.prime, mp)) != CRYPT_OK) goto cleanup; + } + else { + if ((err = ltc_mp.ecc_mul2add(mG, s, mQ, t, mG, ma, key->dp.prime)) != CRYPT_OK) goto cleanup; + } + if ((err = ltc_mp_add(e, mG->x, R)) != CRYPT_OK) goto cleanup; + if ((err = ltc_mp_mod(R, key->dp.order, R)) != CRYPT_OK) goto cleanup; + + if (ltc_mp_cmp(R, r) == LTC_MP_EQ) *stat = 1; + err = CRYPT_OK; + +cleanup: + if (mG != NULL) ltc_ecc_del_point(mG); + if (mQ != NULL) ltc_ecc_del_point(mQ); + if (mu != NULL) ltc_mp_clear(mu); + if (ma != NULL) ltc_mp_clear(ma); + if (mp != NULL) ltc_mp_montgomery_free(mp); + ltc_mp_deinit_multi(r, s, t, e, R, a_plus3, LTC_NULL); + return err; +} + +/** + Verify an SM2 signature against a message + @param id The signer identifier used to compute ZA + @param idlen The length of the signer identifier in octets + @param msg The message to verify + @param msglen The length of the message in octets + @param sig The DER-encoded signature to verify + @param siglen The length of the signature in octets + @param hash_idx The index of the hash to use for ZA and message digesting, or -1 to use the default SM3 hash + @param stat [out] 1 if the signature is valid, 0 if it is invalid + @param key The ECC key containing the public key to verify with; it must use the built-in sm2p256v1 curve + @return CRYPT_OK if successful + @note The default hash is SM3. Other hashes should only rarely be used in practice. +*/ +int ecc_verify_sm2(const unsigned char *id, unsigned long idlen, + const unsigned char *msg, unsigned long msglen, + const unsigned char *sig, unsigned long siglen, + int hash_idx, int *stat, const ecc_key *key) +{ + unsigned char digest[MAXBLOCKSIZE]; + unsigned long digestlen = sizeof(digest); + int err; + + LTC_ARGCHK(id != NULL); + LTC_ARGCHK(msg != NULL); + LTC_ARGCHK(sig != NULL); + LTC_ARGCHK(stat != NULL); + LTC_ARGCHK(key != NULL); + + if ((err = s_sm2_only_curve(key)) != CRYPT_OK) return err; + if ((err = s_sm2_digest_message(digest, &digestlen, id, idlen, msg, msglen, hash_idx, key)) != CRYPT_OK) return err; + return s_ecc_verify_hash_sm2(sig, siglen, digest, digestlen, stat, key); +} +#endif /* LTC_DER */ + +/** + Encrypt a message with SM2 public-key encryption + @param in The plaintext to encrypt + @param inlen The length of the plaintext in octets + @param out [out] The destination for the ciphertext in C1 || C3 || C2 format + @param outlen [in/out] The max size and resulting size of the ciphertext + @param prng An active PRNG state + @param wprng The index of the PRNG to use + @param hash_idx The index of the hash to use for KDF and C3, or -1 to use the default SM3 hash + @param key The ECC key containing the recipient public key; it must use the built-in sm2p256v1 curve + @return CRYPT_OK if successful + @note The default hash is SM3. Other hashes should only rarely be used in practice. +*/ +int ecc_encrypt_key_sm2(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen, + prng_state *prng, int wprng, + int hash_idx, const ecc_key *key) +{ + ecc_key pubkey; + unsigned char *mask = NULL, *xy = NULL, *c3 = NULL; + unsigned long need, c1len, hashsize, i; + int err, have_pubkey = 0, max_iterations; + hash_state md; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + LTC_ARGCHK(key != NULL); + + if ((err = s_sm2_only_curve(key)) != CRYPT_OK) return err; + if ((hash_idx = s_sm2_hash_idx(hash_idx)) < 0) return hash_idx; + if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) return err; + if (key->type != PK_PUBLIC && key->type != PK_PRIVATE) return CRYPT_PK_INVALID_TYPE; + + c1len = 1uL + (2uL * key->dp.size); + hashsize = hash_descriptor[hash_idx].hashsize; + need = c1len + hashsize + inlen; + if (*outlen < need) { + *outlen = need; + return CRYPT_BUFFER_OVERFLOW; + } + + xy = XMALLOC(2uL * key->dp.size); + c3 = XMALLOC(hashsize); + if (xy == NULL || c3 == NULL) { + err = CRYPT_MEM; + goto cleanup; + } + if (inlen > 0uL) { + mask = XMALLOC(inlen); + if (mask == NULL) { + err = CRYPT_MEM; + goto cleanup; + } + } + + /* C1 = scalmult(k, G), (x2, y2) = scalmult(k, PB), mask = KDF(x2 || y2) */ + err = CRYPT_ERROR; + have_pubkey = 0; + for (max_iterations = LTC_PK_MAX_RETRIES; max_iterations > 0; max_iterations--) { + unsigned long tmplen = c1len; + if ((err = ecc_copy_curve(key, &pubkey)) != CRYPT_OK) goto cleanup; + have_pubkey = 1; + if ((err = ecc_generate_key(prng, wprng, &pubkey)) != CRYPT_OK) goto cleanup; + if ((err = ltc_ecc_export_point(out, &tmplen, pubkey.pubkey.x, pubkey.pubkey.y, key->dp.size, 0)) != CRYPT_OK) goto cleanup; + if ((err = s_sm2_shared_xy(&pubkey, key, xy)) != CRYPT_OK) goto cleanup; + if (inlen > 0uL) { + if ((err = s_sm2_kdf(hash_idx, xy, 2uL * key->dp.size, mask, inlen)) != CRYPT_OK) goto cleanup; + } + ecc_free(&pubkey); + have_pubkey = 0; + if (inlen == 0uL || !s_sm2_is_all_zero(mask, inlen)) break; + } + + if (max_iterations == 0) { + err = CRYPT_ERROR; + goto cleanup; + } + + /* C3 = H(x2 || M || y2), C2 = M ^ KDF(x2 || y2) */ + if ((err = hash_descriptor[hash_idx].init(&md)) != CRYPT_OK) goto cleanup; + if ((err = hash_descriptor[hash_idx].process(&md, xy, key->dp.size)) != CRYPT_OK) goto cleanup; + if (inlen > 0uL) { + if ((err = hash_descriptor[hash_idx].process(&md, in, inlen)) != CRYPT_OK) goto cleanup; + } + if ((err = hash_descriptor[hash_idx].process(&md, xy + key->dp.size, key->dp.size)) != CRYPT_OK) goto cleanup; + if ((err = hash_descriptor[hash_idx].done(&md, c3)) != CRYPT_OK) goto cleanup; + XMEMCPY(out + c1len, c3, hashsize); + for (i = 0; i < inlen; i++) { + out[c1len + hashsize + i] = in[i] ^ mask[i]; + } + *outlen = need; + err = CRYPT_OK; + +cleanup: + if (have_pubkey) { + ecc_free(&pubkey); + } +#ifdef LTC_CLEAN_STACK + zeromem(&md, sizeof(md)); + if (mask != NULL) zeromem(mask, inlen); + if (xy != NULL) zeromem(xy, 2uL * key->dp.size); + if (c3 != NULL) zeromem(c3, hashsize); +#endif + if (mask != NULL) XFREE(mask); + if (xy != NULL) XFREE(xy); + if (c3 != NULL) XFREE(c3); + return err; +} + +/** + Decrypt and authenticate an SM2 ciphertext + @param in The ciphertext in C1 || C3 || C2 format + @param inlen The length of the ciphertext in octets + @param out [out] The destination for the recovered plaintext + @param outlen [in/out] The max size and resulting size of the plaintext + @param hash_idx The index of the hash to use for KDF and C3 verification, or -1 to use the default SM3 hash + @param key The private ECC key to decrypt with; it must use the built-in sm2p256v1 curve + @return CRYPT_OK if successful + @note The default hash is SM3. Other hashes should only rarely be used in practice. +*/ +int ecc_decrypt_key_sm2(const unsigned char *in, unsigned long inlen, + unsigned char *out, unsigned long *outlen, + int hash_idx, const ecc_key *key) +{ + ecc_key pubkey; + unsigned char *mask = NULL, *xy = NULL, *u = NULL; + unsigned long c1len, c2len, hashsize, i; + int err, have_pubkey = 0; + hash_state md; + + LTC_ARGCHK(in != NULL); + LTC_ARGCHK(out != NULL); + LTC_ARGCHK(outlen != NULL); + LTC_ARGCHK(key != NULL); + + if ((err = s_sm2_only_curve(key)) != CRYPT_OK) return err; + if ((hash_idx = s_sm2_hash_idx(hash_idx)) < 0) return hash_idx; + if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) return err; + if (key->type != PK_PRIVATE) return CRYPT_PK_NOT_PRIVATE; + if (inlen == 0uL) return CRYPT_INVALID_PACKET; + + if (in[0] == 0x04) { + c1len = 1uL + (2uL * key->dp.size); + } + else if (in[0] == 0x02 || in[0] == 0x03) { + c1len = 1uL + key->dp.size; + } + else { + return CRYPT_INVALID_PACKET; + } + + hashsize = hash_descriptor[hash_idx].hashsize; + if (inlen < c1len + hashsize) return CRYPT_INVALID_PACKET; + + c2len = inlen - c1len - hashsize; + if (*outlen < c2len) { + *outlen = c2len; + return CRYPT_BUFFER_OVERFLOW; + } + + xy = XMALLOC(2uL * key->dp.size); + u = XMALLOC(hashsize); + if (xy == NULL || u == NULL) { + err = CRYPT_MEM; + goto cleanup; + } + if (c2len > 0uL) { + mask = XMALLOC(c2len); + if (mask == NULL) { + err = CRYPT_MEM; + goto cleanup; + } + } + + /* (x2, y2) = scalmult(dB, C1) */ + have_pubkey = 0; + if ((err = ecc_copy_curve(key, &pubkey)) != CRYPT_OK) goto cleanup; + have_pubkey = 1; + if ((err = ecc_set_key(in, c1len, PK_PUBLIC, &pubkey)) != CRYPT_OK) goto cleanup; + if ((err = s_sm2_shared_xy(key, &pubkey, xy)) != CRYPT_OK) goto cleanup; + ecc_free(&pubkey); + have_pubkey = 0; + if (c2len > 0uL) { + if ((err = s_sm2_kdf(hash_idx, xy, 2uL * key->dp.size, mask, c2len)) != CRYPT_OK) goto cleanup; + if (s_sm2_is_all_zero(mask, c2len)) { + err = CRYPT_INVALID_PACKET; + goto cleanup; + } + } + + /* M = C2 ^ KDF(x2 || y2) */ + for (i = 0; i < c2len; i++) { + out[i] = in[c1len + hashsize + i] ^ mask[i]; + } + + /* u = H(x2 || M || y2); verify u == C3 */ + if ((err = hash_descriptor[hash_idx].init(&md)) != CRYPT_OK) goto cleanup; + if ((err = hash_descriptor[hash_idx].process(&md, xy, key->dp.size)) != CRYPT_OK) goto cleanup; + if (c2len > 0uL) { + if ((err = hash_descriptor[hash_idx].process(&md, out, c2len)) != CRYPT_OK) goto cleanup; + } + if ((err = hash_descriptor[hash_idx].process(&md, xy + key->dp.size, key->dp.size)) != CRYPT_OK) goto cleanup; + if ((err = hash_descriptor[hash_idx].done(&md, u)) != CRYPT_OK) goto cleanup; + + if (XMEM_NEQ(u, in + c1len, hashsize) != 0) { + err = CRYPT_INVALID_PACKET; + goto cleanup; + } + + *outlen = c2len; + err = CRYPT_OK; + +cleanup: + if (have_pubkey) { + ecc_free(&pubkey); + } +#ifdef LTC_CLEAN_STACK + zeromem(&md, sizeof(md)); + if (mask != NULL) zeromem(mask, c2len); + if (xy != NULL) zeromem(xy, 2uL * key->dp.size); + if (u != NULL) zeromem(u, hashsize); +#endif + if (mask != NULL) XFREE(mask); + if (xy != NULL) XFREE(xy); + if (u != NULL) XFREE(u); + return err; +} + +#endif /* LTC_MECC */ diff --git a/tests/ecc_sm2_test.c b/tests/ecc_sm2_test.c new file mode 100644 index 000000000..9c55a3f08 --- /dev/null +++ b/tests/ecc_sm2_test.c @@ -0,0 +1,273 @@ +/* LibTomCrypt, modular cryptographic library -- Tom St Denis */ +/* SPDX-License-Identifier: Unlicense */ +#include + +#if defined(LTC_MECC) && defined(LTC_DER) && defined(LTC_SM3) && defined(LTC_ECC_SM2P256V1) + +static const unsigned char s_sm2_test_priv_der[] = { + 0x30, 0x77, 0x02, 0x01, 0x01, 0x04, 0x20, 0x63, 0xa0, 0x63, 0x0a, 0x53, 0x91, 0x57, 0x1c, + 0x8a, 0x57, 0x32, 0x8d, 0x72, 0x09, 0xa9, 0x40, 0x42, 0xaf, 0xf0, 0x77, 0x9b, 0xd3, 0x8a, + 0xf9, 0x00, 0x1a, 0x99, 0xc9, 0x9d, 0xb4, 0xda, 0xf6, 0xa0, 0x0a, 0x06, 0x08, 0x2a, 0x81, + 0x1c, 0xcf, 0x55, 0x01, 0x82, 0x2d, 0xa1, 0x44, 0x03, 0x42, 0x00, 0x04, 0x69, 0xe1, 0xa4, + 0x14, 0xe7, 0xcd, 0xe8, 0x0f, 0xa4, 0x06, 0xed, 0x10, 0x75, 0x88, 0x0e, 0x82, 0x74, 0x98, + 0x98, 0x70, 0xff, 0x3b, 0x8c, 0x97, 0xcb, 0x46, 0x30, 0x15, 0x56, 0xde, 0x37, 0x25, 0x7b, + 0xc2, 0x3a, 0xaf, 0x05, 0x14, 0x3d, 0x69, 0x2b, 0x9b, 0x93, 0x54, 0xf9, 0x95, 0x78, 0xe3, + 0xcb, 0xd2, 0x04, 0xc2, 0xd0, 0x20, 0x71, 0x6f, 0xad, 0x7a, 0x6f, 0x75, 0x6c, 0xca, 0x9d, + 0xd2 +}; + +static const unsigned char s_sm2_test_pub[] = { + 0x04, 0x69, 0xe1, 0xa4, 0x14, 0xe7, 0xcd, 0xe8, 0x0f, 0xa4, 0x06, 0xed, 0x10, 0x75, 0x88, + 0x0e, 0x82, 0x74, 0x98, 0x98, 0x70, 0xff, 0x3b, 0x8c, 0x97, 0xcb, 0x46, 0x30, 0x15, 0x56, + 0xde, 0x37, 0x25, 0x7b, 0xc2, 0x3a, 0xaf, 0x05, 0x14, 0x3d, 0x69, 0x2b, 0x9b, 0x93, 0x54, + 0xf9, 0x95, 0x78, 0xe3, 0xcb, 0xd2, 0x04, 0xc2, 0xd0, 0x20, 0x71, 0x6f, 0xad, 0x7a, 0x6f, + 0x75, 0x6c, 0xca, 0x9d, 0xd2 +}; + +static const unsigned char s_sm2_test_user_id[] = { + 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, + 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38 +}; + +/* Source: draft-shen-sm2-ecdsa-02, Appendix A.2 "Digital Signature of over E(Fp)" + and Appendix C.2 "Encryption and Decryption over E(Fp)". + + These are published example vectors for the draft's Fp-256 example curve, + not for the built-in sm2p256v1/curveSM2 parameters. +*/ +static const char s_sm2_draft_fp256_p[] = "8542D69E4C044F18E8B92435BF6FF7DE457283915C45517D722EDB8B08F1DFC3"; +static const char s_sm2_draft_fp256_a[] = "787968B4FA32C3FD2417842E73BBFEFF2F3C848B6831D7E0EC65228B3937E498"; +static const char s_sm2_draft_fp256_b[] = "63E4C6D3B23B0C849CF84241484BFE48F61D59A5B16BA06E6E12D1DA27C5249A"; +static const char s_sm2_draft_fp256_n[] = "8542D69E4C044F18E8B92435BF6FF7DD297720630485628D5AE74EE7C32E79B7"; +static const char s_sm2_draft_fp256_gx[] = "421DEBD61B62EAB6746434EBC3CC315E32220B3BADD50BDC4C4E6C147FEDD43D"; +static const char s_sm2_draft_fp256_gy[] = "0680512BCBB42C07D47349D2153B70C4E5D7FDFCBFA36EA1A85841B9E46E09A2"; + +/* Source: draft-shen-sm2-ecdsa-02, Appendix A.1/A.2 */ +static const unsigned char s_sm2_draft_sig_id[] = "ALICE123@YAHOO.COM"; +static const unsigned char s_sm2_draft_sig_msg[] = "message digest"; +static const char s_sm2_draft_sig_pub_x[] = "0AE4C7798AA0F119471BEE11825BE46202BB79E2A5844495E97C04FF4DF2548A"; +static const char s_sm2_draft_sig_pub_y[] = "7C0240F88F1CD4E16352A73C17B7F16F07353E53A176D684A9FE0C6BB798E857"; +static const char s_sm2_draft_sig_r[] = "40F1EC59F793D9F49E09DCEF49130D4194F79FB1EED2CAA55BACDB49C4E755D1"; +static const char s_sm2_draft_sig_s[] = "6FC6DAC32C5D5CF10C77DFB20F7C2EB667A457872FB09EC56327A67EC7DEEBE7"; + +/* Source: draft-shen-sm2-ecdsa-02, Appendix C.2 */ +static const char s_sm2_draft_enc_priv[] = "1649AB77A00637BD5E2EFE283FBF353534AA7F7CB89463F208DDBC2920BB0DA0"; +static const char s_sm2_draft_enc_c1_x[] = "245C26FB68B1DDDDB12C4B6BF9F2B6D5FE60A383B0D18D1C4144ABF17F6252E7"; +static const char s_sm2_draft_enc_c1_y[] = "76CB9264C2A7E88E52B19903FDC47378F605E36811F5C07423A24B84400F01B8"; +static const char s_sm2_draft_enc_c2[] = "650053A89B41C418B0C3AAD00D886C00286467"; +static const char s_sm2_draft_enc_c3[] = "9C3D7360C30156FAB7C80A0276712DA9D8094A634B766D3A285E07480653426D"; + +/* Source: generated with OpenSSL 3.0.13: + openssl genpkey -algorithm SM2 -out key.pem + printf %s "OpenSSL SM2 vector" > msg.bin + openssl dgst -sm3 -sign key.pem -sigopt distid:OpenSSL-with-SM2 -out sig.bin msg.bin + openssl pkey -in key.pem -pubout -outform DER -out pub.der +*/ +static const unsigned char s_sm2_openssl_msg[] = "OpenSSL SM2 vector"; +static const unsigned char s_sm2_openssl_id[] = "OpenSSL-with-SM2"; +static const unsigned char s_sm2_openssl_pub_der[] = { + 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, + 0x01, 0x06, 0x08, 0x2a, 0x81, 0x1c, 0xcf, 0x55, 0x01, 0x82, 0x2d, 0x03, + 0x42, 0x00, 0x04, 0x1c, 0x44, 0x0a, 0xe5, 0x88, 0x20, 0x02, 0x36, 0x77, + 0xc9, 0x2a, 0x70, 0xbf, 0x4c, 0xc4, 0x9c, 0xe3, 0xb1, 0x03, 0xb6, 0x93, + 0x9a, 0x22, 0x52, 0x5b, 0x07, 0xbb, 0x09, 0xa2, 0xb2, 0x7e, 0x4d, 0x1f, + 0xda, 0x22, 0xdc, 0x08, 0xc0, 0xdf, 0x83, 0x1c, 0xeb, 0x53, 0x06, 0x2f, + 0x62, 0x81, 0xa0, 0x64, 0xe4, 0xed, 0xde, 0x24, 0x1c, 0xa4, 0x90, 0x28, + 0x58, 0x51, 0x49, 0xbf, 0x90, 0xf6, 0x80 +}; +static const unsigned char s_sm2_openssl_sig_der[] = { + 0x30, 0x45, 0x02, 0x20, 0x2c, 0xf8, 0x57, 0x9e, 0x14, 0x72, 0xb0, 0xf3, + 0x84, 0xd2, 0x97, 0xf1, 0x48, 0x02, 0x27, 0x46, 0xeb, 0xdc, 0x54, 0x9d, + 0xd3, 0x88, 0x9d, 0x71, 0x93, 0x75, 0x06, 0xa0, 0xa3, 0xc1, 0x55, 0x12, + 0x02, 0x21, 0x00, 0xc3, 0xec, 0x35, 0xc3, 0xec, 0xf1, 0x81, 0x94, 0xa7, + 0x02, 0xe4, 0xad, 0xe6, 0xc0, 0x53, 0x5b, 0x95, 0xe2, 0x9b, 0x44, 0x65, + 0xf0, 0x21, 0x20, 0x4a, 0x0c, 0x1d, 0x57, 0x84, 0xd9, 0xc1, 0x49 +}; + +static int s_sm2_set_custom_curve(ecc_key *key) +{ + void *a = NULL, *b = NULL, *p = NULL, *n = NULL, *gx = NULL, *gy = NULL; + int err; + + if ((err = ltc_mp_init_multi(&a, &b, &p, &n, &gx, &gy, LTC_NULL)) != CRYPT_OK) return err; + if ((err = ltc_mp_read_radix(a, s_sm2_draft_fp256_a, 16)) != CRYPT_OK) goto cleanup; + if ((err = ltc_mp_read_radix(b, s_sm2_draft_fp256_b, 16)) != CRYPT_OK) goto cleanup; + if ((err = ltc_mp_read_radix(p, s_sm2_draft_fp256_p, 16)) != CRYPT_OK) goto cleanup; + if ((err = ltc_mp_read_radix(n, s_sm2_draft_fp256_n, 16)) != CRYPT_OK) goto cleanup; + if ((err = ltc_mp_read_radix(gx, s_sm2_draft_fp256_gx, 16)) != CRYPT_OK) goto cleanup; + if ((err = ltc_mp_read_radix(gy, s_sm2_draft_fp256_gy, 16)) != CRYPT_OK) goto cleanup; + err = ecc_set_curve_from_mpis(a, b, p, n, gx, gy, 1uL, key); + +cleanup: + ltc_mp_deinit_multi(a, b, p, n, gx, gy, LTC_NULL); + return err; +} + +static int s_sm2_set_public_point(ecc_key *key, const char *x, const char *y) +{ + int err; + + if ((err = ltc_mp_read_radix(key->pubkey.x, x, 16)) != CRYPT_OK) return err; + if ((err = ltc_mp_read_radix(key->pubkey.y, y, 16)) != CRYPT_OK) return err; + if ((err = ltc_mp_set(key->pubkey.z, 1)) != CRYPT_OK) return err; + key->type = PK_PUBLIC; + return CRYPT_OK; +} + +static int s_sm2_set_private_scalar(ecc_key *key, const char *d) +{ + int err; + + if ((err = ltc_mp_read_radix(key->k, d, 16)) != CRYPT_OK) return err; + key->type = PK_PRIVATE; + return CRYPT_OK; +} + +static int s_sm2_sig_der_from_hex(const char *r_hex, const char *s_hex, unsigned char *out, unsigned long *outlen) +{ + void *r = NULL, *s = NULL; + int err; + + if ((err = ltc_mp_init_multi(&r, &s, LTC_NULL)) != CRYPT_OK) return err; + if ((err = ltc_mp_read_radix(r, r_hex, 16)) != CRYPT_OK) goto cleanup; + if ((err = ltc_mp_read_radix(s, s_hex, 16)) != CRYPT_OK) goto cleanup; + err = der_encode_sequence_multi(out, outlen, + LTC_ASN1_INTEGER, 1uL, r, + LTC_ASN1_INTEGER, 1uL, s, + LTC_ASN1_EOL, 0uL, LTC_NULL); + +cleanup: + ltc_mp_deinit_multi(r, s, LTC_NULL); + return err; +} + +int ecc_sm2_test(void) +{ + static const unsigned char msg[] = "encryption standard"; + unsigned char id_bad[sizeof(s_sm2_test_user_id)]; + unsigned char msg_bad[sizeof(msg)]; + unsigned char sig[256], ct[256], pt[sizeof(msg)], draft_sig[80], draft_ct[256]; + unsigned char pubbuf[sizeof(s_sm2_test_pub)]; + unsigned long len, siglen, ctlen, ptlen, draft_siglen, draft_ctlen, partlen; + const ltc_ecc_curve *dp; + ecc_key privkey = { 0 }, pubkey = { 0 }, draft_pubkey = { 0 }, draft_privkey = { 0 }, openssl_pubkey = { 0 }; + int err, stat, hash_idx, prng_idx; + + hash_idx = find_hash("sm3"); + if (hash_idx < 0) return CRYPT_NOP; + prng_idx = find_prng("yarrow"); + + DO(ecc_import_openssl(s_sm2_test_priv_der, sizeof(s_sm2_test_priv_der), &privkey)); + DO(ecc_find_curve("SM2", &dp)); + DO(ecc_set_curve(dp, &pubkey)); + DO(ecc_set_key(s_sm2_test_pub, sizeof(s_sm2_test_pub), PK_PUBLIC, &pubkey)); + + len = sizeof(pubbuf); + DO(ecc_ansi_x963_export(&privkey, pubbuf, &len)); + COMPARE_TESTVECTOR(pubbuf, len, s_sm2_test_pub, sizeof(s_sm2_test_pub), "SM2 public key import", 0); + + siglen = sizeof(sig); + DO(ecc_sign_sm2(s_sm2_test_user_id, sizeof(s_sm2_test_user_id), msg, sizeof(msg) - 1uL, + sig, &siglen, &yarrow_prng, prng_idx, -1, &privkey)); + stat = 0; + DO(ecc_verify_sm2(s_sm2_test_user_id, sizeof(s_sm2_test_user_id), msg, sizeof(msg) - 1uL, + sig, siglen, -1, &stat, &pubkey)); + if (stat != 1) { + err = CRYPT_FAIL_TESTVECTOR; + goto cleanup; + } + + XMEMCPY(id_bad, s_sm2_test_user_id, sizeof(id_bad)); + id_bad[0] ^= 1; + stat = 0; + DO(ecc_verify_sm2(id_bad, sizeof(id_bad), msg, sizeof(msg) - 1uL, sig, siglen, -1, &stat, &pubkey)); + if (stat != 0) { + err = CRYPT_FAIL_TESTVECTOR; + goto cleanup; + } + + XMEMCPY(msg_bad, msg, sizeof(msg)); + msg_bad[0] ^= 1; + stat = 0; + DO(ecc_verify_sm2(s_sm2_test_user_id, sizeof(s_sm2_test_user_id), msg_bad, sizeof(msg) - 1uL, + sig, siglen, -1, &stat, &pubkey)); + if (stat != 0) { + err = CRYPT_FAIL_TESTVECTOR; + goto cleanup; + } + + ctlen = sizeof(ct); + DO(ecc_encrypt_key_sm2(msg, sizeof(msg) - 1uL, ct, &ctlen, + &yarrow_prng, prng_idx, -1, &pubkey)); + ptlen = sizeof(pt); + DO(ecc_decrypt_key_sm2(ct, ctlen, pt, &ptlen, -1, &privkey)); + COMPARE_TESTVECTOR(pt, ptlen, msg, sizeof(msg) - 1uL, "SM2 decrypt", 2); + + ct[ctlen - 1uL] ^= 1; + ptlen = sizeof(pt); + SHOULD_FAIL(ecc_decrypt_key_sm2(ct, ctlen, pt, &ptlen, -1, &privkey)); + + DO(s_sm2_set_custom_curve(&draft_pubkey)); + DO(s_sm2_set_public_point(&draft_pubkey, s_sm2_draft_sig_pub_x, s_sm2_draft_sig_pub_y)); + + /* Source: draft-shen-sm2-ecdsa-02, Appendix A.2. The draft publishes raw r,s values; the public API expects DER. + The example uses a non-SM2 draft curve and is expected to be rejected by the public SM2 API. */ + draft_siglen = sizeof(draft_sig); + DO(s_sm2_sig_der_from_hex(s_sm2_draft_sig_r, s_sm2_draft_sig_s, draft_sig, &draft_siglen)); + stat = 0; + SHOULD_FAIL(ecc_verify_sm2(s_sm2_draft_sig_id, sizeof(s_sm2_draft_sig_id) - 1uL, + s_sm2_draft_sig_msg, sizeof(s_sm2_draft_sig_msg) - 1uL, + draft_sig, draft_siglen, hash_idx, &stat, &draft_pubkey)); + + DO(s_sm2_set_custom_curve(&draft_privkey)); + DO(s_sm2_set_private_scalar(&draft_privkey, s_sm2_draft_enc_priv)); + + /* Source: draft-shen-sm2-ecdsa-02, Appendix C.2 publishes C = C1 || C2 || C3. + libtomcrypt's SM2 public API uses C1 || C3 || C2, so the test reorders the published pieces. + The example uses a non-SM2 draft curve and is expected to be rejected by the public SM2 API. */ + draft_ctlen = 0; + draft_ct[draft_ctlen++] = 0x04; + partlen = sizeof(draft_ct) - draft_ctlen; + DO(base16_decode(s_sm2_draft_enc_c1_x, XSTRLEN(s_sm2_draft_enc_c1_x), draft_ct + draft_ctlen, &partlen)); + draft_ctlen += partlen; + partlen = sizeof(draft_ct) - draft_ctlen; + DO(base16_decode(s_sm2_draft_enc_c1_y, XSTRLEN(s_sm2_draft_enc_c1_y), draft_ct + draft_ctlen, &partlen)); + draft_ctlen += partlen; + partlen = sizeof(draft_ct) - draft_ctlen; + DO(base16_decode(s_sm2_draft_enc_c3, XSTRLEN(s_sm2_draft_enc_c3), draft_ct + draft_ctlen, &partlen)); + draft_ctlen += partlen; + partlen = sizeof(draft_ct) - draft_ctlen; + DO(base16_decode(s_sm2_draft_enc_c2, XSTRLEN(s_sm2_draft_enc_c2), draft_ct + draft_ctlen, &partlen)); + draft_ctlen += partlen; + + ptlen = sizeof(pt); + SHOULD_FAIL(ecc_decrypt_key_sm2(draft_ct, draft_ctlen, pt, &ptlen, hash_idx, &draft_privkey)); + + DO(ecc_import_openssl(s_sm2_openssl_pub_der, sizeof(s_sm2_openssl_pub_der), &openssl_pubkey)); + stat = 0; + DO(ecc_verify_sm2(s_sm2_openssl_id, sizeof(s_sm2_openssl_id) - 1uL, + s_sm2_openssl_msg, sizeof(s_sm2_openssl_msg) - 1uL, + s_sm2_openssl_sig_der, sizeof(s_sm2_openssl_sig_der), -1, &stat, &openssl_pubkey)); + if (stat != 1) { + err = CRYPT_FAIL_TESTVECTOR; + goto cleanup; + } + + err = CRYPT_OK; +cleanup: + ecc_free(&openssl_pubkey); + ecc_free(&draft_privkey); + ecc_free(&draft_pubkey); + ecc_free(&pubkey); + ecc_free(&privkey); + return err; +} + +#else + +int ecc_sm2_test(void) +{ + return CRYPT_NOP; +} + +#endif diff --git a/tests/ecc_test.c b/tests/ecc_test.c index f2c5ee1bf..8b98ddded 100644 --- a/tests/ecc_test.c +++ b/tests/ecc_test.c @@ -119,6 +119,9 @@ static const char* curvenames[] = { #ifdef LTC_ECC_SECP256K1 "SECP256K1", #endif +#ifdef LTC_ECC_SM2P256V1 + "SM2P256V1", "SM2", +#endif #ifdef LTC_ECC_BRAINPOOLP256R1 "BRAINPOOLP256R1", #endif diff --git a/tests/pem/openssl_sm2_pk.pem b/tests/pem/openssl_sm2_pk.pem new file mode 100644 index 000000000..96666482d --- /dev/null +++ b/tests/pem/openssl_sm2_pk.pem @@ -0,0 +1,4 @@ +-----BEGIN PUBLIC KEY----- +MFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAElv1gjyK3bO/Ozcu93Bv1y2Y0Fk2z +OCiHI+PCNzVR/riiaHlFKwgcAvM3+wzk4fEQ6LnG6hQc7ZMYwgmEwhMcYQ== +-----END PUBLIC KEY----- diff --git a/tests/pem/openssl_sm2_sk.pem b/tests/pem/openssl_sm2_sk.pem new file mode 100644 index 000000000..eb4d5946b --- /dev/null +++ b/tests/pem/openssl_sm2_sk.pem @@ -0,0 +1,5 @@ +-----BEGIN PRIVATE KEY----- +MIGHAgEAMBMGByqGSM49AgEGCCqBHM9VAYItBG0wawIBAQQgblyITq5ntmG3wrHd +KkYJt+ENKrIpm/ILeJ2cR8lr82KhRANCAASW/WCPIrds787Ny73cG/XLZjQWTbM4 +KIcj48I3NVH+uKJoeUUrCBwC8zf7DOTh8RDoucbqFBztkxjCCYTCExxh +-----END PRIVATE KEY----- diff --git a/tests/pem/openssl_sm2_sk_pw.pem b/tests/pem/openssl_sm2_sk_pw.pem new file mode 100644 index 000000000..67810699b --- /dev/null +++ b/tests/pem/openssl_sm2_sk_pw.pem @@ -0,0 +1,7 @@ +-----BEGIN ENCRYPTED PRIVATE KEY----- +MIHsMFcGCSqGSIb3DQEFDTBKMCkGCSqGSIb3DQEFDDAcBAjwNOAHIYZc+wICCAAw +DAYIKoZIhvcNAgkFADAdBglghkgBZQMEASoEEMk8zw02o9MQNuR8qIPxYtAEgZDU +HOHi022PCxdDsTuA4AoljTV5vkaYue3Q6yjgS/W34WpewQgcpgTIxZoEFgeokZdy +uhLHada8Jirzbkd/t8jYJoB4VXAbL5aiY6EfP4mBLX+Ti0KjuWALFUqmB3N02Een +q1au8yVGMQVADodKBdoVDF3bc1ssVBOKn7pPuNvwTLzFr671SDoKehIWK3NaZQ0= +-----END ENCRYPTED PRIVATE KEY----- diff --git a/tests/pem/openssl_sm2_sk_pw_t.pem b/tests/pem/openssl_sm2_sk_pw_t.pem new file mode 100644 index 000000000..d75492d50 --- /dev/null +++ b/tests/pem/openssl_sm2_sk_pw_t.pem @@ -0,0 +1,8 @@ +-----BEGIN EC PRIVATE KEY----- +Proc-Type: 4,ENCRYPTED +DEK-Info: DES-EDE3-CBC,C112A4A66D87EFCC + +bSFjKtF9l3HbYlwvftMn+EFUk1vGhazmpdj22IKgP7IuQMDujIq7+aanpiC/KE5Y +WjdqqQZQ4iZAzQr49V/8XQA3zUPCIVHNcJP2a0uMW7144DLnIK0lO4sddumZJrO9 +XfuT4z5NRg/rr7FIzBmzKjxbxShmIhBkm30stu77Enw= +-----END EC PRIVATE KEY----- diff --git a/tests/pem/openssl_sm2_sk_t.pem b/tests/pem/openssl_sm2_sk_t.pem new file mode 100644 index 000000000..6249ad7c5 --- /dev/null +++ b/tests/pem/openssl_sm2_sk_t.pem @@ -0,0 +1,5 @@ +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEIG5ciE6uZ7Zht8Kx3SpGCbfhDSqyKZvyC3idnEfJa/NioAoGCCqBHM9V +AYItoUQDQgAElv1gjyK3bO/Ozcu93Bv1y2Y0Fk2zOCiHI+PCNzVR/riiaHlFKwgc +AvM3+wzk4fEQ6LnG6hQc7ZMYwgmEwhMcYQ== +-----END EC PRIVATE KEY----- diff --git a/tests/pem/openssl_sm2_x509.pem b/tests/pem/openssl_sm2_x509.pem new file mode 100644 index 000000000..2c77fa54d --- /dev/null +++ b/tests/pem/openssl_sm2_x509.pem @@ -0,0 +1,11 @@ +-----BEGIN CERTIFICATE----- +MIIBgDCCASegAwIBAgIULwy5k37l27WOmqPRr9SfKDC2dmUwCgYIKoEcz1UBg3Uw +FTETMBEGA1UEAwwKQ3J5cHRYLVNNMjAgFw0yNjA0MjExMDEwNDVaGA8yMzAwMDIw +MzEwMTA0NVowFTETMBEGA1UEAwwKQ3J5cHRYLVNNMjBZMBMGByqGSM49AgEGCCqB +HM9VAYItA0IABJb9YI8it2zvzs3Lvdwb9ctmNBZNszgohyPjwjc1Uf64omh5RSsI +HALzN/sM5OHxEOi5xuoUHO2TGMIJhMITHGGjUzBRMB0GA1UdDgQWBBR8tDikwWsh +emlzSKpAou6evOjewTAfBgNVHSMEGDAWgBR8tDikwWshemlzSKpAou6evOjewTAP +BgNVHRMBAf8EBTADAQH/MAoGCCqBHM9VAYN1A0cAMEQCIGO5iw3xQlYZH5m+Lw4/ +3sTgpH54aYFtdrSMwU3A7eHuAiAjxzjncXedOGedUOrrlEujkFgyX42K1rJE5y4d +T/1dCA== +-----END CERTIFICATE----- diff --git a/tests/pem/pkcs/sm2-pkcs8/openssl_sm2_sk.pk8 b/tests/pem/pkcs/sm2-pkcs8/openssl_sm2_sk.pk8 new file mode 100644 index 000000000..eb4d5946b --- /dev/null +++ b/tests/pem/pkcs/sm2-pkcs8/openssl_sm2_sk.pk8 @@ -0,0 +1,5 @@ +-----BEGIN PRIVATE KEY----- +MIGHAgEAMBMGByqGSM49AgEGCCqBHM9VAYItBG0wawIBAQQgblyITq5ntmG3wrHd +KkYJt+ENKrIpm/ILeJ2cR8lr82KhRANCAASW/WCPIrds787Ny73cG/XLZjQWTbM4 +KIcj48I3NVH+uKJoeUUrCBwC8zf7DOTh8RDoucbqFBztkxjCCYTCExxh +-----END PRIVATE KEY----- diff --git a/tests/pem/pkcs/sm2-pkcs8/openssl_sm2_sk_pbes1.pk8 b/tests/pem/pkcs/sm2-pkcs8/openssl_sm2_sk_pbes1.pk8 new file mode 100644 index 000000000..0a218e38a --- /dev/null +++ b/tests/pem/pkcs/sm2-pkcs8/openssl_sm2_sk_pbes1.pk8 @@ -0,0 +1,6 @@ +-----BEGIN ENCRYPTED PRIVATE KEY----- +MIGxMBwGCiqGSIb3DQEMAQMwDgQIuuBddfPeCtYCAggABIGQbMxseKJaE/bMMPIu +IrnRqJNf8+W+r4TXzqHTJE4PVg30sp76L2hwGQ/wA7w92EDOpmdmFKW48xPo17+m +gPu2q8Zd7nX6WevOEU3XyOdkYMnQ8GxJJVqkymWJ4/XvY+obXYP3FBMpW4WxkSIU +xMxsb9s5Bt9AUeqFavGlXvKPSZnEgEBtBneMJjbu39rSiKaB +-----END ENCRYPTED PRIVATE KEY----- diff --git a/tests/pem/pkcs/sm2-pkcs8/openssl_sm2_sk_pbes2.pk8 b/tests/pem/pkcs/sm2-pkcs8/openssl_sm2_sk_pbes2.pk8 new file mode 100644 index 000000000..cca120373 --- /dev/null +++ b/tests/pem/pkcs/sm2-pkcs8/openssl_sm2_sk_pbes2.pk8 @@ -0,0 +1,7 @@ +-----BEGIN ENCRYPTED PRIVATE KEY----- +MIHsMFcGCSqGSIb3DQEFDTBKMCkGCSqGSIb3DQEFDDAcBAj0sOgpHSc83QICCAAw +DAYIKoZIhvcNAgsFADAdBglghkgBZQMEASoEECr8nFhdYEII9amMenox/M0EgZD3 +K3vvLjFe6ueZ1Ci+rxGNYFy2kYXWdqOLi7wou46Fz3Eh2H1ajNOyZDajlfPgBtcx +6ZCeBe2gQuQeyJg9lzmohshAB6tDgNCeBanPWBcrG3yrJNjCPm9ZALwwfkQpJpE3 +pENlAIxOJABy2oVARXEXwFC4nNhqz3iBswGG2zwTR1IMoTobshm/X5FqSTtbY60= +-----END ENCRYPTED PRIVATE KEY----- diff --git a/tests/pem_test.c b/tests/pem_test.c index 4dc14cbd7..3b7dff0a2 100644 --- a/tests/pem_test.c +++ b/tests/pem_test.c @@ -93,6 +93,48 @@ static int s_key_cmp(ltc_pka_key *key) return CRYPT_INVALID_ARG; } +static int s_pem_only_decode_pkcs(const void *in, unsigned long inlen, void *key); + +#if defined(LTC_MECC) +static int s_sm2_key_cmp(ltc_pka_key *key) +{ + const ltc_ecc_curve *curve; + char oid[64]; + unsigned long oidlen = sizeof(oid); + int err; + + LTC_ARGCHK(key != NULL); + + if (key->id != LTC_PKA_EC) return CRYPT_INVALID_ARG; + if (key->u.ecc.type != PK_PRIVATE) return CRYPT_INVALID_ARG; + if ((err = ecc_find_curve("SM2", &curve)) != CRYPT_OK) return err; + if ((err = ecc_get_oid_str(oid, &oidlen, &key->u.ecc)) != CRYPT_OK) return err; + if (XSTRCMP(oid, curve->OID) != 0) return CRYPT_ERROR; + return CRYPT_OK; +} + +static int s_pem_decode_sm2_pkcs(const void *in, unsigned long inlen, void *key) +{ + int err; + + if ((err = s_pem_only_decode_pkcs(in, inlen, key)) != CRYPT_OK) { + return err; + } + return s_sm2_key_cmp(key); +} + +static int s_pem_decode_sm2_pkcs_f(FILE *f, void *key) +{ + int err; + password_ctx pw_ctx = { .callback = password_get }; + + if ((err = pem_decode_pkcs_filehandle(f, key, &pw_ctx)) != CRYPT_OK) { + return err; + } + return s_sm2_key_cmp(key); +} +#endif + static int s_pem_decode_invalid_pkcs(const void *in, unsigned long inlen, void *key) { password_ctx pw_ctx = { .callback = password_get }; @@ -164,6 +206,8 @@ int pem_test(void) DO(test_process_dir("tests/pem/pkcs", &key, NULL, s_pem_decode_pkcs_f, (dir_cleanup_cb)pka_key_free, "pem_pkcs_test_filehandle")); DO(test_process_dir("tests/pem/pkcs/ecc-pkcs8", &key, s_pem_decode_pkcs, NULL, (dir_cleanup_cb)pka_key_free, "pem_pkcs_test+ecc")); DO(test_process_dir("tests/pem/pkcs/ecc-pkcs8", &key, NULL, s_pem_decode_pkcs_f, (dir_cleanup_cb)pka_key_free, "pem_pkcs_test_filehandle+ecc")); + DO(test_process_dir("tests/pem/pkcs/sm2-pkcs8", &key, s_pem_decode_sm2_pkcs, NULL, (dir_cleanup_cb)pka_key_free, "pem_pkcs_test+sm2")); + DO(test_process_dir("tests/pem/pkcs/sm2-pkcs8", &key, NULL, s_pem_decode_sm2_pkcs_f, (dir_cleanup_cb)pka_key_free, "pem_pkcs_test_filehandle+sm2")); DO(test_process_dir("tests/pem/pkcs/extra", &key, s_pem_only_decode_pkcs, NULL, (dir_cleanup_cb)pka_key_free, "pem_pkcs_test+extra")); DO(test_process_dir("tests/pem/pkcs/invalid", &key, s_pem_decode_invalid_pkcs, NULL, NULL, "pem_test_invalid")); DO(test_process_dir("tests/pem/pkcs/invalid_but_supported", &key, s_pem_only_decode_pkcs, NULL, (dir_cleanup_cb)pka_key_free, "pem_pkcs_invalid_but_supported")); diff --git a/tests/test.c b/tests/test.c index a88ef0910..218542ce3 100644 --- a/tests/test.c +++ b/tests/test.c @@ -31,6 +31,7 @@ static const test_function test_functions[] = LTC_TEST_FN(rsa_test), LTC_TEST_FN(dh_test), LTC_TEST_FN(ecc_test), + LTC_TEST_FN(ecc_sm2_test), LTC_TEST_FN(dsa_test), LTC_TEST_FN(ed25519_test), LTC_TEST_FN(x25519_test), diff --git a/tests/tomcrypt_test.h b/tests/tomcrypt_test.h index 747ede567..a0471bf6a 100644 --- a/tests/tomcrypt_test.h +++ b/tests/tomcrypt_test.h @@ -27,6 +27,7 @@ int rotate_test(void); int rsa_test(void); int dh_test(void); int ecc_test(void); +int ecc_sm2_test(void); int dsa_test(void); int der_test(void); int misc_test(void); From 3888ec7a45dafe51cdb3ba73665610d8d98de1b5 Mon Sep 17 00:00:00 2001 From: Karel Miko Date: Tue, 21 Apr 2026 20:58:15 +0200 Subject: [PATCH 5/9] Update makefiles --- libtomcrypt_VS2008.vcproj | 4 ++++ makefile.mingw | 17 +++++++++-------- makefile.msvc | 17 +++++++++-------- makefile.unix | 17 +++++++++-------- makefile_include.mk | 17 +++++++++-------- sources.cmake | 1 + tests/sources.cmake | 1 + 7 files changed, 42 insertions(+), 32 deletions(-) diff --git a/libtomcrypt_VS2008.vcproj b/libtomcrypt_VS2008.vcproj index 27868ef6f..4314e51e7 100644 --- a/libtomcrypt_VS2008.vcproj +++ b/libtomcrypt_VS2008.vcproj @@ -2594,6 +2594,10 @@ RelativePath="src\pk\ecc\ecc_sizes.c" > + + diff --git a/makefile.mingw b/makefile.mingw index 1f9c3e013..45e44f322 100644 --- a/makefile.mingw +++ b/makefile.mingw @@ -200,8 +200,8 @@ src/pk/ecc/ecc_recover_key.o src/pk/ecc/ecc_rfc6979_key.o src/pk/ecc/ecc_set_cur src/pk/ecc/ecc_set_curve_internal.o src/pk/ecc/ecc_set_key.o src/pk/ecc/ecc_shared_secret.o \ src/pk/ecc/ecc_sign_hash.o src/pk/ecc/ecc_sign_hash_eth27.o src/pk/ecc/ecc_sign_hash_internal.o \ src/pk/ecc/ecc_sign_hash_rfc5656.o src/pk/ecc/ecc_sign_hash_rfc7518.o src/pk/ecc/ecc_sign_hash_x962.o \ -src/pk/ecc/ecc_sizes.o src/pk/ecc/ecc_ssh_ecdsa_encode_name.o src/pk/ecc/ecc_verify_hash.o \ -src/pk/ecc/ecc_verify_hash_eth27.o src/pk/ecc/ecc_verify_hash_internal.o \ +src/pk/ecc/ecc_sizes.o src/pk/ecc/ecc_sm2.o src/pk/ecc/ecc_ssh_ecdsa_encode_name.o \ +src/pk/ecc/ecc_verify_hash.o src/pk/ecc/ecc_verify_hash_eth27.o src/pk/ecc/ecc_verify_hash_internal.o \ src/pk/ecc/ecc_verify_hash_rfc5656.o src/pk/ecc/ecc_verify_hash_rfc7518.o \ src/pk/ecc/ecc_verify_hash_x962.o src/pk/ecc/ltc_ecc_export_point.o src/pk/ecc/ltc_ecc_import_point.o \ src/pk/ecc/ltc_ecc_is_point.o src/pk/ecc/ltc_ecc_is_point_at_infinity.o src/pk/ecc/ltc_ecc_map.o \ @@ -240,12 +240,13 @@ src/stream/sosemanuk/sosemanuk_memory.o src/stream/sosemanuk/sosemanuk_test.o #List of test objects to compile TOBJECTS=tests/argon2_test.o tests/base16_test.o tests/base32_test.o tests/base64_test.o \ tests/bcrypt_test.o tests/cipher_hash_test.o tests/common.o tests/deprecated_test.o tests/der_test.o \ -tests/dh_test.o tests/dsa_test.o tests/ecc_test.o tests/ed25519_test.o tests/file_test.o tests/mac_test.o \ -tests/misc_test.o tests/modes_test.o tests/mpi_test.o tests/multi_test.o \ -tests/no_null_termination_check_test.o tests/no_prng.o tests/padding_test.o tests/pem_test.o \ -tests/pk_oid_test.o tests/pkcs_1_eme_test.o tests/pkcs_1_emsa_test.o tests/pkcs_1_oaep_test.o \ -tests/pkcs_1_pss_test.o tests/pkcs_1_test.o tests/prng_test.o tests/rotate_test.o tests/rsa_test.o \ -tests/scrypt_test.o tests/ssh_test.o tests/store_test.o tests/test.o tests/x25519_test.o +tests/dh_test.o tests/dsa_test.o tests/ecc_sm2_test.o tests/ecc_test.o tests/ed25519_test.o \ +tests/file_test.o tests/mac_test.o tests/misc_test.o tests/modes_test.o tests/mpi_test.o \ +tests/multi_test.o tests/no_null_termination_check_test.o tests/no_prng.o tests/padding_test.o \ +tests/pem_test.o tests/pk_oid_test.o tests/pkcs_1_eme_test.o tests/pkcs_1_emsa_test.o \ +tests/pkcs_1_oaep_test.o tests/pkcs_1_pss_test.o tests/pkcs_1_test.o tests/prng_test.o \ +tests/rotate_test.o tests/rsa_test.o tests/scrypt_test.o tests/ssh_test.o tests/store_test.o tests/test.o \ +tests/x25519_test.o #The following headers will be installed by "make install" HEADERS_PUB=src/headers/tomcrypt.h src/headers/tomcrypt_argchk.h src/headers/tomcrypt_cfg.h \ diff --git a/makefile.msvc b/makefile.msvc index 5d92f6e4b..6341d3ab3 100644 --- a/makefile.msvc +++ b/makefile.msvc @@ -193,8 +193,8 @@ src/pk/ecc/ecc_recover_key.obj src/pk/ecc/ecc_rfc6979_key.obj src/pk/ecc/ecc_set src/pk/ecc/ecc_set_curve_internal.obj src/pk/ecc/ecc_set_key.obj src/pk/ecc/ecc_shared_secret.obj \ src/pk/ecc/ecc_sign_hash.obj src/pk/ecc/ecc_sign_hash_eth27.obj src/pk/ecc/ecc_sign_hash_internal.obj \ src/pk/ecc/ecc_sign_hash_rfc5656.obj src/pk/ecc/ecc_sign_hash_rfc7518.obj src/pk/ecc/ecc_sign_hash_x962.obj \ -src/pk/ecc/ecc_sizes.obj src/pk/ecc/ecc_ssh_ecdsa_encode_name.obj src/pk/ecc/ecc_verify_hash.obj \ -src/pk/ecc/ecc_verify_hash_eth27.obj src/pk/ecc/ecc_verify_hash_internal.obj \ +src/pk/ecc/ecc_sizes.obj src/pk/ecc/ecc_sm2.obj src/pk/ecc/ecc_ssh_ecdsa_encode_name.obj \ +src/pk/ecc/ecc_verify_hash.obj src/pk/ecc/ecc_verify_hash_eth27.obj src/pk/ecc/ecc_verify_hash_internal.obj \ src/pk/ecc/ecc_verify_hash_rfc5656.obj src/pk/ecc/ecc_verify_hash_rfc7518.obj \ src/pk/ecc/ecc_verify_hash_x962.obj src/pk/ecc/ltc_ecc_export_point.obj src/pk/ecc/ltc_ecc_import_point.obj \ src/pk/ecc/ltc_ecc_is_point.obj src/pk/ecc/ltc_ecc_is_point_at_infinity.obj src/pk/ecc/ltc_ecc_map.obj \ @@ -233,12 +233,13 @@ src/stream/sosemanuk/sosemanuk_memory.obj src/stream/sosemanuk/sosemanuk_test.ob #List of test objects to compile TOBJECTS=tests/argon2_test.obj tests/base16_test.obj tests/base32_test.obj tests/base64_test.obj \ tests/bcrypt_test.obj tests/cipher_hash_test.obj tests/common.obj tests/deprecated_test.obj tests/der_test.obj \ -tests/dh_test.obj tests/dsa_test.obj tests/ecc_test.obj tests/ed25519_test.obj tests/file_test.obj tests/mac_test.obj \ -tests/misc_test.obj tests/modes_test.obj tests/mpi_test.obj tests/multi_test.obj \ -tests/no_null_termination_check_test.obj tests/no_prng.obj tests/padding_test.obj tests/pem_test.obj \ -tests/pk_oid_test.obj tests/pkcs_1_eme_test.obj tests/pkcs_1_emsa_test.obj tests/pkcs_1_oaep_test.obj \ -tests/pkcs_1_pss_test.obj tests/pkcs_1_test.obj tests/prng_test.obj tests/rotate_test.obj tests/rsa_test.obj \ -tests/scrypt_test.obj tests/ssh_test.obj tests/store_test.obj tests/test.obj tests/x25519_test.obj +tests/dh_test.obj tests/dsa_test.obj tests/ecc_sm2_test.obj tests/ecc_test.obj tests/ed25519_test.obj \ +tests/file_test.obj tests/mac_test.obj tests/misc_test.obj tests/modes_test.obj tests/mpi_test.obj \ +tests/multi_test.obj tests/no_null_termination_check_test.obj tests/no_prng.obj tests/padding_test.obj \ +tests/pem_test.obj tests/pk_oid_test.obj tests/pkcs_1_eme_test.obj tests/pkcs_1_emsa_test.obj \ +tests/pkcs_1_oaep_test.obj tests/pkcs_1_pss_test.obj tests/pkcs_1_test.obj tests/prng_test.obj \ +tests/rotate_test.obj tests/rsa_test.obj tests/scrypt_test.obj tests/ssh_test.obj tests/store_test.obj tests/test.obj \ +tests/x25519_test.obj #The following headers will be installed by "make install" HEADERS_PUB=src/headers/tomcrypt.h src/headers/tomcrypt_argchk.h src/headers/tomcrypt_cfg.h \ diff --git a/makefile.unix b/makefile.unix index 349610ef0..f05585c09 100644 --- a/makefile.unix +++ b/makefile.unix @@ -214,8 +214,8 @@ src/pk/ecc/ecc_recover_key.o src/pk/ecc/ecc_rfc6979_key.o src/pk/ecc/ecc_set_cur src/pk/ecc/ecc_set_curve_internal.o src/pk/ecc/ecc_set_key.o src/pk/ecc/ecc_shared_secret.o \ src/pk/ecc/ecc_sign_hash.o src/pk/ecc/ecc_sign_hash_eth27.o src/pk/ecc/ecc_sign_hash_internal.o \ src/pk/ecc/ecc_sign_hash_rfc5656.o src/pk/ecc/ecc_sign_hash_rfc7518.o src/pk/ecc/ecc_sign_hash_x962.o \ -src/pk/ecc/ecc_sizes.o src/pk/ecc/ecc_ssh_ecdsa_encode_name.o src/pk/ecc/ecc_verify_hash.o \ -src/pk/ecc/ecc_verify_hash_eth27.o src/pk/ecc/ecc_verify_hash_internal.o \ +src/pk/ecc/ecc_sizes.o src/pk/ecc/ecc_sm2.o src/pk/ecc/ecc_ssh_ecdsa_encode_name.o \ +src/pk/ecc/ecc_verify_hash.o src/pk/ecc/ecc_verify_hash_eth27.o src/pk/ecc/ecc_verify_hash_internal.o \ src/pk/ecc/ecc_verify_hash_rfc5656.o src/pk/ecc/ecc_verify_hash_rfc7518.o \ src/pk/ecc/ecc_verify_hash_x962.o src/pk/ecc/ltc_ecc_export_point.o src/pk/ecc/ltc_ecc_import_point.o \ src/pk/ecc/ltc_ecc_is_point.o src/pk/ecc/ltc_ecc_is_point_at_infinity.o src/pk/ecc/ltc_ecc_map.o \ @@ -254,12 +254,13 @@ src/stream/sosemanuk/sosemanuk_memory.o src/stream/sosemanuk/sosemanuk_test.o #List of test objects to compile (all goes to libtomcrypt_prof.a) TOBJECTS=tests/argon2_test.o tests/base16_test.o tests/base32_test.o tests/base64_test.o \ tests/bcrypt_test.o tests/cipher_hash_test.o tests/common.o tests/deprecated_test.o tests/der_test.o \ -tests/dh_test.o tests/dsa_test.o tests/ecc_test.o tests/ed25519_test.o tests/file_test.o tests/mac_test.o \ -tests/misc_test.o tests/modes_test.o tests/mpi_test.o tests/multi_test.o \ -tests/no_null_termination_check_test.o tests/no_prng.o tests/padding_test.o tests/pem_test.o \ -tests/pk_oid_test.o tests/pkcs_1_eme_test.o tests/pkcs_1_emsa_test.o tests/pkcs_1_oaep_test.o \ -tests/pkcs_1_pss_test.o tests/pkcs_1_test.o tests/prng_test.o tests/rotate_test.o tests/rsa_test.o \ -tests/scrypt_test.o tests/ssh_test.o tests/store_test.o tests/test.o tests/x25519_test.o +tests/dh_test.o tests/dsa_test.o tests/ecc_sm2_test.o tests/ecc_test.o tests/ed25519_test.o \ +tests/file_test.o tests/mac_test.o tests/misc_test.o tests/modes_test.o tests/mpi_test.o \ +tests/multi_test.o tests/no_null_termination_check_test.o tests/no_prng.o tests/padding_test.o \ +tests/pem_test.o tests/pk_oid_test.o tests/pkcs_1_eme_test.o tests/pkcs_1_emsa_test.o \ +tests/pkcs_1_oaep_test.o tests/pkcs_1_pss_test.o tests/pkcs_1_test.o tests/prng_test.o \ +tests/rotate_test.o tests/rsa_test.o tests/scrypt_test.o tests/ssh_test.o tests/store_test.o tests/test.o \ +tests/x25519_test.o #The following headers will be installed by "make install" HEADERS_PUB=src/headers/tomcrypt.h src/headers/tomcrypt_argchk.h src/headers/tomcrypt_cfg.h \ diff --git a/makefile_include.mk b/makefile_include.mk index 702ff5a1d..c1ec2721a 100644 --- a/makefile_include.mk +++ b/makefile_include.mk @@ -385,8 +385,8 @@ src/pk/ecc/ecc_recover_key.o src/pk/ecc/ecc_rfc6979_key.o src/pk/ecc/ecc_set_cur src/pk/ecc/ecc_set_curve_internal.o src/pk/ecc/ecc_set_key.o src/pk/ecc/ecc_shared_secret.o \ src/pk/ecc/ecc_sign_hash.o src/pk/ecc/ecc_sign_hash_eth27.o src/pk/ecc/ecc_sign_hash_internal.o \ src/pk/ecc/ecc_sign_hash_rfc5656.o src/pk/ecc/ecc_sign_hash_rfc7518.o src/pk/ecc/ecc_sign_hash_x962.o \ -src/pk/ecc/ecc_sizes.o src/pk/ecc/ecc_ssh_ecdsa_encode_name.o src/pk/ecc/ecc_verify_hash.o \ -src/pk/ecc/ecc_verify_hash_eth27.o src/pk/ecc/ecc_verify_hash_internal.o \ +src/pk/ecc/ecc_sizes.o src/pk/ecc/ecc_sm2.o src/pk/ecc/ecc_ssh_ecdsa_encode_name.o \ +src/pk/ecc/ecc_verify_hash.o src/pk/ecc/ecc_verify_hash_eth27.o src/pk/ecc/ecc_verify_hash_internal.o \ src/pk/ecc/ecc_verify_hash_rfc5656.o src/pk/ecc/ecc_verify_hash_rfc7518.o \ src/pk/ecc/ecc_verify_hash_x962.o src/pk/ecc/ltc_ecc_export_point.o src/pk/ecc/ltc_ecc_import_point.o \ src/pk/ecc/ltc_ecc_is_point.o src/pk/ecc/ltc_ecc_is_point_at_infinity.o src/pk/ecc/ltc_ecc_map.o \ @@ -430,12 +430,13 @@ endif # List of test objects to compile (all goes to libtomcrypt_prof.a) TOBJECTS=tests/argon2_test.o tests/base16_test.o tests/base32_test.o tests/base64_test.o \ tests/bcrypt_test.o tests/cipher_hash_test.o tests/common.o tests/deprecated_test.o tests/der_test.o \ -tests/dh_test.o tests/dsa_test.o tests/ecc_test.o tests/ed25519_test.o tests/file_test.o tests/mac_test.o \ -tests/misc_test.o tests/modes_test.o tests/mpi_test.o tests/multi_test.o \ -tests/no_null_termination_check_test.o tests/no_prng.o tests/padding_test.o tests/pem_test.o \ -tests/pk_oid_test.o tests/pkcs_1_eme_test.o tests/pkcs_1_emsa_test.o tests/pkcs_1_oaep_test.o \ -tests/pkcs_1_pss_test.o tests/pkcs_1_test.o tests/prng_test.o tests/rotate_test.o tests/rsa_test.o \ -tests/scrypt_test.o tests/ssh_test.o tests/store_test.o tests/test.o tests/x25519_test.o +tests/dh_test.o tests/dsa_test.o tests/ecc_sm2_test.o tests/ecc_test.o tests/ed25519_test.o \ +tests/file_test.o tests/mac_test.o tests/misc_test.o tests/modes_test.o tests/mpi_test.o \ +tests/multi_test.o tests/no_null_termination_check_test.o tests/no_prng.o tests/padding_test.o \ +tests/pem_test.o tests/pk_oid_test.o tests/pkcs_1_eme_test.o tests/pkcs_1_emsa_test.o \ +tests/pkcs_1_oaep_test.o tests/pkcs_1_pss_test.o tests/pkcs_1_test.o tests/prng_test.o \ +tests/rotate_test.o tests/rsa_test.o tests/scrypt_test.o tests/ssh_test.o tests/store_test.o tests/test.o \ +tests/x25519_test.o # The following headers will be installed by "make install" HEADERS_PUB=src/headers/tomcrypt.h src/headers/tomcrypt_argchk.h src/headers/tomcrypt_cfg.h \ diff --git a/sources.cmake b/sources.cmake index 82383087d..1a7a26f8c 100644 --- a/sources.cmake +++ b/sources.cmake @@ -445,6 +445,7 @@ src/pk/ecc/ecc_sign_hash_rfc5656.c src/pk/ecc/ecc_sign_hash_rfc7518.c src/pk/ecc/ecc_sign_hash_x962.c src/pk/ecc/ecc_sizes.c +src/pk/ecc/ecc_sm2.c src/pk/ecc/ecc_ssh_ecdsa_encode_name.c src/pk/ecc/ecc_verify_hash.c src/pk/ecc/ecc_verify_hash_eth27.c diff --git a/tests/sources.cmake b/tests/sources.cmake index ae348a644..75fe821de 100644 --- a/tests/sources.cmake +++ b/tests/sources.cmake @@ -10,6 +10,7 @@ deprecated_test.c der_test.c dh_test.c dsa_test.c +ecc_sm2_test.c ecc_test.c ed25519_test.c file_test.c From 49ba2a9ee62fed858c1b46f599f2e4ba84c300a8 Mon Sep 17 00:00:00 2001 From: Karel Miko Date: Tue, 21 Apr 2026 21:08:40 +0200 Subject: [PATCH 6/9] fix verify docs... check --- doc/crypt.tex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/crypt.tex b/doc/crypt.tex index 4c30a234d..e6a9df689 100644 --- a/doc/crypt.tex +++ b/doc/crypt.tex @@ -5279,7 +5279,7 @@ \chapter{Elliptic Curve Cryptography - $GF(p)$} \hline \texttt{secp224k1} & & 1.3.132.0.32 \\ \hline \texttt{secp256r1} & nistp256, prime256v1, ECC-256, P-256 & 1.2.840.10045.3.1.7 \\ \hline \texttt{secp256k1} & & 1.3.132.0.10 \\ -\hline \texttt{sm2p256v1} & SM2P256V1, SM2 & 1.2.156.10197.1.301 \\ +\hline \texttt{sm2p256v1} & sm2 & 1.2.156.10197.1.301 \\ \hline \texttt{secp384r1} & nistp384, ECC-384, P-384 & 1.3.132.0.34 \\ \hline \texttt{secp521r1} & nistp521, ECC-521, P-521 & 1.3.132.0.35 \\ \hline \texttt{prime239v1} & & 1.2.840.10045.3.1.4 \\ From 337443fe609f8ce3aa8f26cdcf99c0be93d7453d Mon Sep 17 00:00:00 2001 From: Karel Miko Date: Tue, 21 Apr 2026 21:28:59 +0200 Subject: [PATCH 7/9] update ecc_tv.txt --- notes/ecc_tv.txt | 163 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 163 insertions(+) diff --git a/notes/ecc_tv.txt b/notes/ecc_tv.txt index 626cf14f8..8a358d619 100644 --- a/notes/ecc_tv.txt +++ b/notes/ecc_tv.txt @@ -1716,6 +1716,169 @@ A0D2E82CA5E358392DE9951D10B533E405FF396E226444B3B8F22B54A64B, 5F0BECA7E9C2AB7143 1019BD50604787981171AF769DE93406E6FDB21EDF9F6BC4C216F6888479E82B, AEA86534CCEFB766C37A3995153208B3B3AD8BECFB696BCA7D2A43743609C8A4, 3CDEEE07A21418F63AC2AC16731C973EC2720C3247667305B6CCBD3E661F5FF8 304D37F120D696C834550E63D9BB9C14B4F9165C9EDE434E4644E3998D6DB881, 6CA8788ED729508CB7B401B1722648C66A1F219EFC845F79CF94815E5ED9A76E, 14426936DD17B2B73EA11EB2519795D49851F02E88346A9EE58623C10BE84337 90E7A7D36283C4589CFF2B2B8D32D43E1EEB4315DC9AC9EAD2CEAACCA8492983, C0E75D94899DFB4373E95D5C1EA6EF32F7396955DA923DDBF8FD57B39BD0CD3A, 8CAB60CDC6A17D2EBC7BA436C08DE8A34B24FAF543E25934AE02909C1E3CAB01 +1.2.156.10197.1.301 +1, 32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7, BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0 +3, A97F7CD4B3C993B4BE2DAA8CDB41E24CA13F6BD945302244E26918F1D0509EBF, 530B5DD88C688EF5CCC5CEC08A72150F7C400EE5CD045292AAACDD037458F6E6 +9, A27233F3A59595080B4A2444A46A74C5FE8D59CB43619E4F173472A58CCA247E, 379E72F63722C924768F7689B210F45FC3A8433140D1EBCA85227940922C02E9 +1B, EC6F34CEACAA73A0D7A1F169475B4DDF02A85A7410754529CE37E84FC9541B4B, 3C85CF62A744817E6F251C63FBBD2927E607F33BE20135EA73306A0FF0485872 +51, 4DA8BBB0F99FFECBC78C20AEC8A5FDFE27F1086E10C87EE97D1A4A46CBEFCCD9, CD4588F38A097BEB4505E94B0635A09E6888BCBDFF421C66C62E8CA1D2255A8E +F3, D7024C3AC1A6D90CEF200622675D49F907A4EB3B4B8E8CFDCA70212744447558, BF75A9960AF6A4249F1CC6537857AF20030E135FCB8673A05C54FCEC35596BF2 +2D9, CF54172025E0102333AA8D6D93D5C427174121FD0EC7D5E88590E156842C09A6, 6F8010D74F8B81CEBF4DD06590321D13ACC164C38B5D2733FFB6B8EAFB7FDA1F +88B, 8E53F6DEC2C2B83FFA09659AEA2AB1F8B0F7A6B50A692873FA9E0C2347A8B91E, B773FA84F939CE68699925BDC0B27FCADB1FA749546F99B01EE055C46F1C7B3 +19A1, 425F18DB0D3FE9C469A188A0A2B00C5B95BDB66F71E92503BF2BBC7B705F9FF, 26428F44757473623887406F0519C993CC98B03E3ABAAE87BDF8B87D7054F1C2 +4CE3, B5BDF3D101E3B5DD1118914C0A863A8EFAED3B96D82237665881461EE3B339DB, 86ED1AE899A8D4CB627E536DFC598489E351F87C10317CF93FC14784504460C9 +E6A9, A103B5A907BAC8BCDEF95CDDE9D9301C7A586F9FEE15CF2EF791390C27EA9BE7, F27235DA78C22FD9DE1545086B717ACF468B004D23C754442E3A3329FA87E316 +2B3FB, 929531595212F88C4ED913D8F00B06CDB107736EBE0B2909B9A561BA774BB002, 3CFE50E01DDACE8621E8074EBE1326A78503F97EBADC4C0DF6AE04B920AD93CF +81BF1, BE6BEEC6D0C262EF302E73C6CCC9574EEDA2C4CFD4762EA759AA58B41A957056, 8C786F30A80EDEE28F68903613479D8137C6114350113B9A3142D67F90B67B51 +1853D3, 424020EDC0D95E6BCCFA71468C97B5758B1E5AB76C14B1618EC33D962553429A, 3CB3170F5FD713208D9F6B387E456D902B7400BB93DA3A4D8F41D9BF40293BA1 +48FB79, 18077235D665AF3FA0F4744A7E7E47CBB792EAF6E13CFA0457C61A232FE0CFDD, CDBA6DD5702255F64387FE046B8D218D3AC2D977ECE614C6B2F8320348408CD7 +DAF26B, 3CF891163BB95CFADFCC74EFCA104165315BAB40CA9A619C710EC2979E2B8E55, 776B3822C62B129C193E02136D2D1E80A58FC73B723CC6416DFF6B403F85CE23 +290D741, DA816B38B75BD37AEACCA7A94036CE0D11E23EF2AE3714992F218678A2702FAC, 7FE251BC59A6E6288D42639A2185C3D1D8CE4C2C70236ABF085A2862619CD9E1 +7B285C3, EE3B088032F6D15DE64F46B1B9C6A692E8BE80F955FF35CE266DBA75355B4006, BC1ECFD02DCEF11904719F1EB6D7D4D058A12AE183066203E841452619837BDB +17179149, 6854A38F5F6B3D3857D2B3487D581C96B8D7C545EE642C452D489B61923FF1DE, 57B41FA073A29EE142FCE56851923D70A6A7D75B121DA843433398E5EC6C1B0E +4546B3DB, EF40BA13AA9872534070A4A5EBA1A3759236D9EFF72616889E6D18576A25CAEA, E2B3213553D409CAF78F1D59DBBEAAFDCB8C925AAB257B520A10F9D33C7A4EDD +CFD41B91, 3FD8897CE0F194C02FAD1FA3F8B75507A856D5A65BC49C3109B6DA11E0350709, 8206AF37F883A704D7216483FE8E20E00EC55193B05211F4EEB43817D827919B +26F7C52B3, 3421D703F904017A694223FD06740AB71752B81B06318CDFEF4E41C933BEBA34, 195E4DD67E6D21AC3ABD0DAD358E329CE5AD9BB7DEC2387B636E28BB3153C0FE +74E74F819, 64153CD6BF88E29C4B12BABB4F16EDBAB96ACEAA3A40C398C5E34D9A191A1F7C, 32B54805185C6DE4371B839E26B47D762448B324F92352114E08236E6C361D50 +15EB5EE84B, D389B8C39EF54F2A9B57866471832CFD7050B79064D9C56C909243DF3396C4E, C1D4FCFC43FF89B39AE9E89BAB1B55589B9B9B6B544C5F28BB16259C05AA4F8A +41C21CB8E1, 7093AAE79B93C16665638BD3DB4834A2CF24510043ABD7D9E6D6DE70BCA13D43, 720E519FD978BF87EB7DB3FA44350A01E931E9F69586A780A93C1064CB16880A +C546562AA3, B1685085CBD5BAD4B5314DBAB79185FB68A538832DEA4E7ECF41FED08189C94C, B42A9A427FC4853D5C470592C7A352FA2F1CB325CACC30F8A723C49F6A485659 +24FD3027FE9, DA9E9DAF9CFE99CA0FB71B1302264ACF339F327D1485D0E4A7C30D41B6B74E1B, AFDBF299B6B9B56D9EC075405BBD735D8A30A1F5185FE64493C1156089B044DB +6EF79077FBB, 2F0135DE22D7BF9FAD6BE9F480AAC3D20F3FFE766567742E7DB664F272C9098, 64BFB0B4321F2D27B0A14EB2EF373CB88ADB42E0AF9D14DD1481DF9B8EF3996B +14CE6B167F31, 3170B38FE9FF97B48C1197E2E6559A028C8B082BF8CE00C5D6EEA99C574A20A7, 6842A23C0B7CE3A6653D434CB3F58E7A955B4664D97E15BFC696C3397D34CBEF +3E6B41437D93, A669D297E4B6C3FACA2E471BF3B36BB5E8174CD2B995080FEEAA8EA7BEF5E70E, CEFF96090A325E3992BF449EB9599B33D3CE0E966EE157CB8718D3E648A872D4 +BB41C3CA78B9, 2CD55ACF5291B2B62AB9D4EF03A8345232FAA326874E7F6B1652F04EEF37C9D6, 74E30B366C948D2A6C9858CD6AA370DAFBDBEB0FF1BB381239CD8EB42B3D766B +231C54B5F6A2B, 9497994167E34641E094A0D778BE2184B2BD100C8CDB1093C8EB94D95146787B, 89759C4D530E76A94549E738FF441AB6E9D3162A31D273D3FCB82CF0D4B3E5A +6954FE21E3E81, 297E40BB440AE72B5C8D8C322EA79FA0CE77A77C85B85A90878F060A4D27EE61, 20D4C518F281495B48741D72BBED1239CF06177DC6B0C74411FF7219BC0F3250 +13BFEFA65ABB83, 5761A8B6243B6F4BE2191241705EDA294E3BC0DF2DE3C3D5102401E88D8BBB4E, D3CDBB9EC4F21007DF89458F90AE4EFB7CB9CCA060B16DA7C12CC598374F9FD0 +3B3FCEF3103289, 4DC3F1235D79014DD9394E9947E19D0AC7BF95C0E16FDEE8E5F343F7AB3B257E, E2C2846C9E2CA08AD75517FCFF6C2FFB5589232C72E1E9420D3F1404CBE5D2CC +B1BF6CD930979B, D84C6054FF8E1764BD7DE86173049A78638A1BC5D026060DC747EA694D566BB6, 86673087E04B5E246757C37A7FE70AD10A0AFFA1280C5FEA8FDC7089D63BC89B +2153E468B91C6D1, 6125E2132FD79DD3E49ABCA8A57641D588AB751C64E2A7786652AC39675C9AE3, E1DFF2982DBF6411838B356DE8FED9C24B4C476F17794C744242EFE496AAA0E5 +63FBAD3A2B55473, CD3FF0B810068EB88F89DB87CCB3B3077C34870AE327A6AEC513578128B84232, F5A7015EF05D9C6C41C82F762FCE99F11B8C2B3AEC1B05AEEBF948AC919557E9 +12BF307AE81FFD59, F1E251AFEC658EC98F55955116C3258B292958B8DA2A3481F2441AE2B54016BA, 3CD831191DCC5736A4238BE38C292FFB02A2A1706B7D5D9300C63C1C1582542 +383D9170B85FF80B, 2C40AB717BE8B97C4B09FBE8265C20E8E9DA27FFF4299A8A7DEAE3C472964F37, 10C7E9F99ED2F895FCB044A488AAE2FC36EE3F6000831E2AE501A8029A13405 +A8B8B452291FE821, 9C9DF0E96A147DB1BB5261787523EB46E4A2A4624FA55BC0D2C4CFFC0643FF5D, F3BE35DBBD1E9FA89A2B21C0A161FF0F0DF48185CB2DC4EE1E6011B43EEFDE25 +1FA2A1CF67B5FB863, 755E876B616C32A6D55D595A3BCAD52DAB21C6B0201F06DA826268F45A4ED770, E5371C2F975655952F2AE1F38069BDA164FB54DDEFD24FA88E3C2BB88791742E +5EE7E56E3721F2929, 1705C4E48430069A93B4B5F237B34ADBB89AFE1D84C75F00C15D658E9A91E7F7, 6059EAD7DAEB7238886266F7F6F394F6AAAB34BFFEA566DA55D69A7F5C2610B7 +11CB7B04AA565D7B7B, 91A981DD72E08AE1413AC6D7975079CBDC65D6D00964984FA54FA6CC70BD7062, 4612B7E26F41415600E64DF50A4BB8B3167A362EE7939CDAC71F38926E12FB83 +3562710DFF03187271, FA716206B8FD003D56EA64C19C10B269D5B20DEF35A459E08422541F801C8EA0, BE267E3C4785CD24226823558C5BC2CA4E44C08E2B4C5FFA697DC0916F1DE617 +A0275329FD09495753, 2532BAFFA49A1A618232E0BB6DDDF3CD3EA24B4FC63BDF2E63A691C7BD677E46, ED2014C6A2A22FDBC115577EDEAE4E868C26BABE627CF754B47E222F86707D97 +1E075F97DF71BDC05F9, C851B7EC8C1A33D297774773BADE75334D407C708DF2A36FDB6731153F96407B, B33BCD4EAD509023EA7A411C9295687F935E98CD592CFAFFDDE94E31A5CF7D36 +5A161EC79E5539411EB, B86E9B9D56EF63553B7BBBFC9BD749141A462833F53B869F8A478FBB9DC82F21, BD95B04D9A7BFF71DC1B7C6397D4DA7849BA8BF27A2F4E1443A0780A28700124 +10E425C56DAFFABC35C1, 4D6616E50CDDD91F81DE352CD60E2600435AE292ABF12374AB325E48319F313E, D2A5674EF8EE215CF891823B6DF333E5D3BC7637361AEB3320496360233BDB6D +32AC7150490FF034A143, F074A7B6050C4BF065DE558F1E82EBBC882AF2DA70D6F9BA7DC9C3433830AD36, 59A340EEA29ADF87546E723229AD8921849E089631D8F5C2A4A31E5652D7CD48 +980553F0DB2FD09DE3C9, FE2C96966D49535805D23289BF793996CF4D59F1D8E363AF1E759B76E09D7226, B4F06750F4DE01518539E3427D729DC2FD3EEB0B41E76020C69B68B108C2D049 +1C80FFBD2918F71D9AB5B, E2F2098A3268A11EBE8627E84CA4CC69369C27199F1B3328037B0320933000AE, E1DB6C1C5D16E21E0EA39DECD5B4D1260DCFB5573532C808A46B4147F9F1E5BB +5582FF377B4AE558D0211, 837DC694454647EFA659816A3D4951FBFAE69E8B5D09194046A9B0215AA54772, AA07AE2C706D5319FCF9C768A50F4C754DDB690E20157231925CD89D365B3513 +10088FDA671E0B00A70633, 296AA883A5E9E33568032F49C10AAEE3AB5DB1897315447AF9F7630CAEBF938C, 142A88442B982A6D661EF0461B5C823EF4EFAA19494DA32891BE03AE8F9304A8 +3019AF8F355A2101F51299, E7CCC82CFF71FAF101FC68EA0CC60B55F1B566513E2F5E12E445419386A58641, D43E1BA2F5B2B3F18F7C6B5B15E3688F8241C025FCB7F1DE0330CB7F8F0C9F26 +904D0EADA00E6305DF37CB, 30589DF5EAC4A488E0CB6B1BCD79DC69C7FEDDFF7BB951DD3F51F82AD1669CF0, 7531A1F2C54E0F1B53F1E24298983B5FC36631F41EC23B6E5DE78E5738292343 +1B0E72C08E02B29119DA761, B131F30B4FD003D3B232982EDC2F83D47E800CC73CC9C7DE5A1431FB3F5E1132, 59E6A83CEC720F6C78B6D76B50B35346FEAB5F41B7BB08F67E53BE10F4ABDB71 +512B5841AA0817B34D8F623, A579CF753E3D917AD820B4E6145DFF718977F679455168591DB291D5BD4B5839, 9347D98293A2D0C08BB046E47CFB2B7EF0685BD284F672A374ACBC42441ECF53 +F38208C4FE184719E8AE269, 782B2F85B73D407047818F74FC3CD9D15B080BA15E993F880173C216F63F197, C6DA335554710D76CC280C1869F20202E4D7FA4CEBD9A2358F9385DB38CEA1FE +2DA861A4EFA48D54DBA0A73B, 6B600B4779B36BE2423C56D2059EF2F605BEE96EA3D1D859A61E01D7788A0B9E, FBE5A2D0D60AEB5DC13B8AB3A9DA2545867775C06172F70B78A7DFEFC3C85A9 +88F924EECEEDA7FE92E1F5B1, 315C168B5121EA19BD3783D062EDF5DB295D7AC440A1897AD64D94B1F68E6374, 85BB92DFE9D1A21A266162FA029F498972F22243EA80555331967662B9123F2 +19AEB6ECC6CC8F7FBB8A5E113, DE5A2FA3C2E7F2732F826EBAD3A73E824CAAE7F427B666169C46C4C3C337EED4, 950ECEF5B3554E457D835E01FC28FD48FA5F8D4D5E5148AFAB2C985D54DB35C3 +4D0C24C65465AE7F329F1A339, 87A2C45E2D969CA5DEEE4CCA5D8AC798AB2E013A40E3D4EAA27934B42976A43D, 4B6CACC28B17262078EC798B8FA2E1B79B5AF79AC7310FE91A20E3D4F1640EBB +E7246E52FD310B7D97DD4E9AB, C03F88141B208E186A56187DB90C35FFC248A851FBD1F1C0B6CB027D499FE47B, D1A68B0FC5EDE684E0997C306E1E41292B08F811B2DF50191389CCEDDE386451 +2B56D4AF8F7932278C797EBD01, FB4D9615F5742E7DB95939698CDE186631539FDEF380AEE2F7CA08D05DC083FC, 4670BD02263F5992E9B959639AA6DC83CFA4F41D06DE0DDA2BDF0C99AAF2A78C +82047E0EAE6B9676A56C7C3703, 8671645DBA494D1E113BCFFE0553A20978DC4ED4E55285EF372E9114097E8739, 15B6C8805ED096F40E2D2FC167576B34DD013CF42CA5AD74A8A493F584204496 +1860D7A2C0B42C363F04574A509, CE679C9DC9F668E2419071DA35FFBEC6DAAFF91A1587CADEE8F6A7A65CD958EE, 9581008FB5C327637FFC157DCDF09C9F4523213024259504E649CA93E3C2932C +492286E8421C84A2BD0D05DEF1B, 42347A08A5302C63C6DE522ABA66D55E35AFD662164B79E1B940855EFB587EED, 6B5CEE0019727D0D37D39CB298CE7EB370E4114A37D0D905E32F2A93932CB4A1 +DB6794B8C6558DE83727119CD51, 41E17AF4A064AF42EB2B0B4125574B764C3F5955D7704088D65B6F19D6705E45, 32B97037968E104FE7A0D2053AA72A43053497E1B99F1DB5C0DF1F90F34BFFB5 +29236BE2A5300A9B8A57534D67F3, 1924AC68DB28CE65C1006DB96ABE6C3EE40ECF9F172548F7F292B282923199C2, 936E47A09D41F4097953A65FFB6645062E67F86C217A3469456ED8F7866B0F42 +7B6A43A7EF901FD29F05F9E837D9, E7C550C4E78A63FE5814962A7E176A8CEBCB72F5D3D0F269EF2A7C41523E2DC2, EDA64F3AFF1F286BE2143E9F19F7F4E005AD1F0C69D0560F53F23B7C47D68C42 +1723ECAF7CEB05F77DD11EDB8A78B, 5E2E334BAED5123BAD6067BA16CC7A8DA9FF90BE202F75362E84D1DD2F787027, 2293B7E35A93BA66323264AAA23E93DFA4BB0FB142659F532A95F2BCC53C5F9A +456BC60E76C111E679735C929F6A1, 7F871C8585265036E3C1EC0CBB945321E728639F65D7FA28EAB29B32390E4572, AEF809CF66E372553261D24DA8162CDDDA9FAC699C9D44530B6BB09A0CD2D0BE +D043522B644335B36C5A15B7DE3E3, 35584765F7CFD280463F5B28708914D68645DFDD50BDAD86219DCA2E382ACCE6, D1518439023D4C3F1FE834C57392EC085862451F69AB16F7C539573621F2F000 +270C9F6822CC9A11A450E41279ABA9, DE9985C53E8B4058B37BB169DD65F64A9AA743845D0BD97A29C808F8E10AFCEF, 43731BE2D99B1619D09192D0B6628EB773EE74DF09AE5063C4520C8E00F5CBD +7525DE386865CE34ECF2AC376D02FB, C1BEC35DF96FCA720F4E7A7C0EAF44EE0CDEF5661D9C802F655182024A217270, 46A2BA008EEFCA16F4A1F572DB98D76B5A8098844A333821E154AE9D8B4A1849 +15F719AA939316A9EC6D804A64708F1, 96B21732179BC56DB3F1B64D318C2CF6F9D7534EE0BB515FA1497CBD04B1B87, 50A2270F29684442F926375E93172B589260F0C9012E5D47CCE8B5B2F2E08FEC +41E54CFFBAB943FDC54880DF2D51AD3, B0D4E993536D68B2D8F19887151607507D0459B664595E90D8E2935A3AC42BE2, 14A3C7C90E5B4CDD55843532AB1FE989FB70041CBDFDF9D981367A1797ADFABB +C5AFE6FF302BCBF94FD9829D87F5079, 71BAA12F6B0773065769B54429C727BF4CBEF5806D3DE8CCEAC4ACF0FF16C7D7, 33AA175447523581A1EA64B0D20AE7F49DDEB0244A30C23857F3C240F4116480 +2510FB4FD908363EBEF8C87D897DF16B, E1071D372092682162C1AB34224334AC3486D149C26528FF3212CCBA662B8617, 24F513F0983FE1ACEF5B5F14A236C6A43AECE5F6E331B4E5C113353C33B13826 +6F32F1EF8B18A2BC3CEA59789C79D441, C22E9FE9F4CE33F7A395C8C5B68B5FDEC86690483F8D1C2DE060F30327EF01C8, 6051A196AF3A160D1458AF620DB769CF4AE8CEA68BE1F29F6F9C146698B49F06 +14D98D5CEA149E834B6BF0C69D56D7CC3, E4B169E994D52F301EF746A5F792D69466D77F70E3D929D0708FF0AB8B89C409, C1E2E7A3E05F7BAB855A613E62BBC6DB0BFDBC0B29BA324A45E939C76428EC31 +3E8CA816BE3DDB89E243D253D80487649, 2B7695D6370F36B5BF8B4C1D0BA26F3D14A977005828F8DD14BD58571D3C4DBD, A3BE8E91FE8280EE5B28C3506406C516903DF7F863BD68CD18048F2A9DA1078 +BBA5F8443AB9929DA6CB76FB880D962DB, 5922BF4BE42CD1629E7DA57F862F2CBAD8F9909198866EDAFE9DDD49BA112968, AEC55A21874EE0B728A88ACD6512C812C2C954AC07AF98FAF961641823C06AE0 +232F1E8CCB02CB7D8F46264F29828C2891, A38A07AB4B6DC40C92AC3482A3A2C06CEB6C5E7FE8FEB7684FE15E3348FD1B2, B14386CBB4A1DD487CFF4A4F047CC0757A53495EBAC4A83E973CB603D51F7AC7 +698D5BA661086278ADD272ED7C87A479B3, 9B08B56B6E4EB6AE1F55A397DEF9A62F94F6B4F6426A19C81A808B5A971EA03D, F00AF532FC814BFF4BFA4E75E5E74AEB87B8F53CF85ABC81C495081BC3541467 +13CA812F32319276A097758C87596ED6D19, 4405773BF81CF7BB146579890DB484B4C4B58AE2667C7B1CADBA2879DD0A68B8, 49B8CECD7BE7226BA1A95541208F9B4453FB35085A27F603112B7AC5419B4BF9 +3B5F838D9694B763E1C660A5960C4C8474B, 7CD519AC0FCF27AEBF1E644F7AAB737D61D96AC8DA0D64D7DDFB4BDE64FF2D9E, 9961B195410050EBF2A8A91C2B725D234FAC54AD8D0D3DCAA528EB06A894CF51 +B21E8AA8C3BE262BA55321F0C224E58D5E1, DC02293DA6CD5851C0EB09D57590521B0A2FDE85B04B2E29FD31BF15A4ED08A7, 27366D2D3962C4027E6E94AE128ACCB217A890D9F399D0696ED8B4E7FB8DB538 +2165B9FFA4B3A7282EFF965D2466EB0A81A3, A9DB314008404EE032806531E24365782ED4BEB7FDF29158B852FE48DC56FDF0, AF0A63B49E11CCEEEEA3B6C944AF87206F3F2A31D26769486A626061B81B7EC +64312DFEEE1AF5788CFEC3176D34C11F84E9, A2BFCB5E4E020D8C564D9B2B47892B75695AA2AA169311255CABCDD61DF01E27, 357A3D38B5DDDBC13323933F0E3A28AC18999780FA4A9980D0E8D1683B0D4FB1 +12C9389FCCA50E069A6FC4946479E435E8EBB, 909E3E9A78E32AB5A46A484D8AF891BF45BDB18B6A8F8BA528CC08E699924C76, 2391C98BB2932E4D684E545513D42BD3265BA7A6AFB1436F4E71D85A13D3234C +385BA9DF65EF2A13CF4F4DBD2D6DACA1BAC31, FE97CA396354EDA3A6B068213FA2820FBAA4F2377E08A9B66B4505473B2C1B28, EF541DAA4ED318D1837F558D71053C69B2EA26DEAA9795B2FF95EB2E4FA4A4E7 +A912FD9E31CD7E3B6DEDE937884905E530493, DD68A139BF827D841E1D1F8243AEDF94A3A8C647C1A5E0FC67A009B27266B94B, 7C0F387E32EBECED38CA3E3E388D6EF8060B74B38E189E07D6BA264F7645FF9F +1FB38F8DA95687AB249C9BBA698DB11AF90DB9, 33D527878000847561CF0BC6678BAB1FE3EEA76B5E5714210B361116B532B52A, C5108D7C9673F13314CFB7118D1CB960945C23269E55A2F0C4353DB42473EA64 +5F1AAEA8FC0397016DD5D32F3CA91350EB292B, AEA4349223C564F30D3FFC7835F411D32BC59EBBC8621AA0BBCE2AC8A1310178, 93D302D7D888B34E2D0CB62FB15B29D289248CEB9367EC196EFDE156F27DC349 +11D500BFAF40AC5044981798DB5FB39F2C17B81, B07F5D110139F1CFC6D0435D6BB1A936250B17805BF2213B76B017ADC97A2A9D, F1711262AC2A0DEE8A75EE211C48914253EBF112F0D0C69BF57D365FA50C9E6D +357F023F0DC204F0CDC846CA921F1ADD8447283, 9B7FABB1CF4170B9B47DE8ED1ED12B1CC775AC424537AF25A5CE97EA89301346, BEA8AC99BC2C8B9B0EF65020729372941C06866D1042F1C8B47234E4A36C1058 +A07D06BD29460ED26958D45FB65D50988CD5789, E659A673A28E536BBD2547305764B3F1BB46CAACFE8C814317EBE50A5B974098, BF50AAC77B978AF67DF7457D454F45FF63DEC69DBAAA7BFE400FA67111242740 +1E17714377BD22C773C0A7D1F2317F1C9A68069B, 4C1E86632667EF8F3367426A840E829803489615721DAFB971DA2A9D6FB1A875, A4C161A88808CF0D9A49DED4669FB179127672BE22F67806956DED0B2BA94DC7 +5A4653CA673768565B41F775D6947D55CF3813D1, 5E3635E2CEFB14522E68642F54135E37A27A9EAB1DACFFCB765FCF092612C5F3, 98DD143DDD0C0114DE2DCE66C9E2714F5F2FD412750F663AD6B5A907F82F9027 +10ED2FB5F35A6390311C5E66183BD78016DA83B73, 504097FC74B279CE243AA9772B9CC4B13E1CB6D0111E9A0E74D2F94906BFD4DD, 1BD4D0A2A081EAA4EBFBC1407AE2E2DE83F36BB88BC99E1CA89519557AC8387B +32C78F21DA0F2AB093551B3248B38680448F8B259, F463238323DA4C1E4369650D7E9CD25D5767DCE37E6A5ACB776E4C7A532898BE, 7EA467FC8341970905038F943D165CE50C21CFFC715986EADFB9D7748E1D1716 +9856AD658E2D8011B9FF5196DA1A9380CDAEA170B, 7DD860B1C7C09C4BDAB44138E5307AEB45FDAEEE70CED12EDBAFA108B543441D, 1EB325B83DBFF9F21538DA707C68574270B0D7F74872B235999DE3F68EDA7552 +1C9040830AA8880352DFDF4C48E4FBA82690BE4521, F03B5B497DDB3B5CC5588730776F94D8B59E525322B9A556F79C9433513752DB, FDB899678A79024ABD8270C6F1165798B25908C0F62EB1DAD898C5DB7254C662 +55B0C1891FF99809F89F9DE4DAAEF2F873B23ACF63, B2618222C3D5134017F30468BF0F999BC70E9AAFC450A7470DE4D137FC02D9FF, 29D774CF9703DD06647D745C9967B55570CFB0A0E18837EA07A87B5BF3968BFA +10112449B5FECC81DE9DED9AE900CD8E95B16B06E29, 8B6173699512F56686C7A652CE03D2A112F40353656314E0C8D0ECCBF490F001, 69C8F978758E8A631F3CFE5FEC15F200BDF51F44E34BC7A355F290337ADC5217 +30336CDD21FC65859BD9C8D0BB0268ABC1144114A7B, E3D45065E7C024205560AF1789F80168381F5AE4430963FF660B65086AA5494D, B9E6F259CC2F924BD0C50643EFF6018EEFEFE14EE10906A710B808A518733BDA +909A469765F53090D38D5A7231073A03433CC33DF71, 24BBDF50A04153AB315DECB6B42EF0AC9A269AFC907C6E104C942E1F19B8C6E6, 8BA9455F251034FEB188AEC2C0842FDBDB48AC0A7304CA13E33C3B44EB17750F +1B1CED3C631DF91B27AA80F569315AE09C9B649B9E53, 49482A71E844E17AD8C559CF77F929DB4BAA45CA8B3A9F369B6849E90899F164, 86181B1BB783092C24C7236897CF64B4B5ED56F61CD54DF7BDF31D78AFCBCAC4 +5156C7B52959EB5176FF82E03B9410A1D5D22DD2DAF9, 2A66528DE312D67036B612BE77C4BE4B6BC402905BC413EE63F38A6978B122AD, F583908A3909C05EB757BF3D7DD697EB37F961F94EA98C5361BD06340F49E3B5 +F404571F7C0DC1F464FE88A0B2BC31E58176897890EB, B0AE3BBF9783C0CDD8F9C67E50930B46F23746DAA99E020653521513D1666A59, 4CB59398DDF567F4071466B5A408EADA818125A799B34D3EC63673E5E994FB61 +2DC0D055E742945DD2EFB99E2183495B084639C69B2C1, A62C77E038A2F49123263F3536F52AE6EF827DC077ED9B78CE66BD3F1BF840EB, 6341FFB6722BDA2CF54E9F41950A1249A75C671DC4E9189690C66EF49FA7B9F4 +89427101B5C7BD1978CF2CDA6489DC1118D2AD53D1843, 40BA9E622A160158310DC896C2FE9F4A30A7EC5A4BB62C61981B570ECF44D697, D8B24904045F54449C6C161493E7F7752AD73FB9C7CD80ED8CD1F66A7D532D8D +19BC753052157374C6A6D868F2D9D94334A7807FB748C9, 3D6D2B39502041B92A7C8560E9F751810A844EFD28988961B4569EA58288E57D, EE9324C9618F8DF412A36B49927B8763C9F522CB508B745730738BA5A129FF61 +4D355F90F6405A5E53F4893AD88D8BC99DF6817F25DA5B, D12653C96227CD2B2898F96F3AE7212CA17BF55C44B791F30D301FB7150ECB59, 58B69720D985E2608F1C2E0DD7B5F06F4A977CE5337046796658B7BBEDD090B5 +E7A01EB2E2C10F1AFBDD9BB089A8A35CD9E3847D718F11, 7B8713615A4B19B2FF0639DF30CA120AD4026DDA80E6319F63BFCA7D2A0AB6CD, 69EB4B86FCEE55B44FEF7EE45514D62A07E9F550EBF4BF961BC0078AC25554DE +2B6E05C18A8432D50F398D3119CF9EA168DAA8D7854AD33, ADA230E47BD62AF34D0D737D1F31FE5FEFAD543192CDE2F1E4A5797A7779B601, 51C353BDB28750407BC6569749E3F18B9E31EEFAB3AAD430F762B35DFAF828B +824A11449F8C987F2DACA7934D6EDBE43A8FFA868FE0799, 2F4D094E99867E241F7FB01212311EC998E4B6D1540DAA9E8EBDC9D5A641E79C, 42DF7723A763AFFB2815BCAF9424337D1B2115462B2EF228733F7134E51EC4BA +186DE33CDDEA5C97D8905F6B9E84C93ACAFAFEF93AFA16CB, 2AE2F32946CFE9020C678F978DEEC10F898777BA1693407FA3CDBF8FDE030ADD, E7418FC5653BB2E663335101670C3D2250C1E9CCC5922C9B00DE18432E3D55E1 +4949A9B699BF15C789B11E42DB8E5BB060F0FCEBB0EE4461, 96833BBD5282D6452C1280C37CBEBD524848B78A0C48533538131A58D459818D, 2DA211466605943168836DCA1FE1A91F090FEE874168D3E1C4C38458BD6B2611 +DBDCFD23CD3D41569D135AC892AB131122D2F6C312CACD23, 89AF35667F8DFE765F4D12A107F4E934488094549D73CDD7B37967A0671EE838, A5E66874D0EE2F29A082F9F23B3DE25D0E9CD667089728F330A202D51CECB022 +29396F76B67B7C403D73A1059B80139336878E44938606769, E701DBBA37EF89F96B9B10D0F46E11726DF9CF4E9BCD0CD29351BD1BAE7C7956, C6A86F1485C1820193F29E55D737DB6F79BCCA13CC3D45A609209C18A1B07B97 +7BAC4E64237274C0B85AE310D2803AB9A396AACDBA921363B, 12A88B364CD63F2045F73BF6ADFCD32741C213A893C4C36C6BC361D72C6BF75E, 6FA1F23325AAFC17DE024CF865C6DCCF706B206CEEBA4B6096B7E700C53F6E4D +17304EB2C6A575E422910A9327780B02CEAC400692FB63A2B1, 5D6833C3484FC7535E439F5A7EE34158B52934D0D91B0EFF1F2137C0C3EDEE22, 4670BF76A9038DD5AB2E9881D3DB0D8577E3FF0F4BC9D1D1DB691815FC501147 +4590EC1853F061AC67B31FB9766821086C04C013B8F22AE813, 25CF881560EDBDB70EEDCFA800D44DFC3E8730C39CA492EF629C8FDC9D02B5CD, 81BE47643869227CA2E87C3582ED28BEE83DAFAEB5A6E7B3B8B3B0818643659D +D0B2C448FBD1250537195F2C63386319440E403B2AD680B839, 512CFA0BDC5AB830696EFDC02690990A5DA74F19868CF9F27B5B524EDE866756, 383DA710FA1B17F0488099E16214D6CB3585352B172F262C0111E0BA260F87D +272184CDAF3736F0FA54C1D8529A9294BCC2AC0B180838228AB, 1FF4F5D26562F3CEC9A67ABFDCAC7B444FD4C840AF6281F73B1CDD7B2714FD17, 2DDC867CF2B47C6B4A0256406C9DEEAB39978431817014BD12BE308A7DAA2955 +75648E690DA5A4D2EEFE4588F7CFB7BE364804214818A867A01, ECADD449E7482A9713B8193A7D7363D513213DD901AB606CA2C142847C4950D5, BC250F50FE9541D543F010B7A346764AAD4F515A674E3BAB2ADB65AF4663D679 +1602DAB3B28F0EE78CCFAD09AE76F273AA2D80C63D849F936E03, BE8219A5352F822097D258AC0AADC76433D15CE4FEC2306B796CF7BBB4CD80D4, 5CE7400B01AAE8687006BC0CF513971D059495B19141A3AFA79F4766071B349F +4208901B17AD2CB6A66F071D0B64D75AFE888252B88DDEBA4A09, E8DBD2BB585AECA2285D2057ECDA0255B237E471F9024D150F2DBAAECD3146ED, 184D5BC1D2B69A94B69F3A693E73A7780646C5A3ED02481E8BAC2F3FCD8D8BA9 +C619B05147078623F34D1557222E8610FB9986F829A99C2EDE1B, 783C4B8B86F7859C1DB452A1871CDFC9109F00E62CAE31EA0EAD50EEAD98487C, C869DD6797D7D371010186E554845AC10E9EC9F660EBB9C137DBB07CCB6684AA +2524D10F3D516926BD9E74005668B9232F2CC94E87CFCD48C9A51, D31A3FC1CC48E8C150FD84B963A6C9D2C6962413DAB480E8C0FBD794ECDE4C17, 7C114E8B2342FD5D345A61288609DC9CBEC27F3ADAC6217D00A139E708371FF7 +6F6E732DB7F43B7438DB5C01033A2B698D865BEB976F67DA5CEF3, F1370E9EBC33006BBE931C3CFDF05AC2F0B8B73F6B21A1F8CBF386EBC1EECD6, ED8BB044282A04997A2B69C61C977BD9429D20C38D45F5B6044A118E789F4C3B +14E4B598927DCB25CAA92140309AE823CA89313C2C64E378F16CD9, AEB822066A618E6A308D49AB9B6EA236238A4735C32EDDE80FACD84640C5EE04, 81397F3351E79912906F9D69D5FEBA9673611A49CF72E1B3F35785B241388B0F +3EAE20C9B77961715FFB63C091D0B86B5F9B93B4852EAA6AD4468B, B298C5AF90D8142D01028F12F11199AB7D27BF03379A1F70E097CBDB1DE8824A, C67A55FFBDDB2D67E8B78D8DB255EEDF6353B28BC735B007EDD1588892253374 +BC0A625D266C24541FF22B41B57229421ED2BB1D8F8BFF407CD3A1, 297A077A00976801A841E894F6034B0625CF405030214E28D3FA9F45D4B9C5AB, 7A5571C798023F6A359999CFFC2E2A780C8EB96CFFE3C24F32BEF330625BD61B +2341F271773446CFC5FD681C520567BC65C783158AEA3FDC1767AE3, 376CA680FD64B43070D10B4E067E41D6DB7901621CFED5989D23E05C043CCA4B, 21A8DFFDEEEE593CBB318284CEC5219B5B7505F5A29707611DDBF048ECF54207 +69C5D754659CD46F51F83854F610373531568940A0BEBF9446370A9, 5EA54F3A330B43D06FD2518660D99EE63C81B95814FE0D7D6FFB42452893B502, 9B365280B8038F22595AD6E1740BA502AACC267086EF24E811B32EB90DF9101E +13D5185FD30D67D4DF5E8A8FEE230A59F94039BC1E23C3EBCD2A51FB, 4515FF5C2464F5A039E7C64678AFB316DE201C0EF57B82F5BD08D0DCF3332487, FFE0062533DF8D1A88725A666089A7AF4DCD4C55E65B7772B086352BD66DA65F +3B7F491F7928377E9E1B9FAFCA691F0DEBC0AD345A6B4BC3677EF5F1, E4FAF4851350E1A2481BF2ED98B5C9A9D9A3E5F45BF50C7B2F377676CF792CEC, 7063044F6BCC9D68A80D76E387A47FEA727BE4AAD0F0035837E5C266B18A9BB2 +B27DDB5E6B78A67BDA52DF0F5F3B5D29C342079D0F41E34A367CE1D3, 55EEBCE72C2A0F9633C19364C1E66B35206564305418AA06D7C7DAE1DD7C3A01, FAFB32334DB2D6F7A3DE446D74099BA0DCF838FAA58DC9DB048D7C8D3D191673 +21779921B4269F3738EF89D2E1DB2177D49C616D72DC5A9DEA376A579, F3772F76FAE0C238AB165086FB838DFF09DA45D0C8030C60F8DCA0DB1F1C9BF8, C9E382986C36E19EA7DDDD30A7F632B7CAD4EA547F89BC7AAD1E41580C8BE29F +6466CB651C73DDA5AACE9D78A59164677DD5244858950FD9BEA63F06B, CAB7AD0269B1B116E4364E7C48F0C1E4F1E748DA1D560C24706974FBBA8673F9, CB317414960714F99979AE3D1CA6B16C5480C90E2FB6D600D49D9848F94EC484 +12D34622F555B98F1006BD869F0B42D36797F6CD909BF2F8D3BF2BD141, 268A8ACF80163E2665C4189A6856C65CF9FAC7992D1AD948722450655CFA0107, D21B374212663A5BD620E0E8ED9F8022CA67410F4ADC82F37C705A10C167BE69 +3879D268E0012CAD30143893DD21C87A36C7E468B1D3D8EA7B3D8373C3, 5AE758280CE03843140491503BAF126E2532C26245CDA6524562A1ADD53BA641, 782E223F6C0030E1B9F32732D581830838FF8B4D9C3A3CA93F663175E5A06E1F +A96D773AA0038607903CA9BB9765596EA457AD3A157B8ABF71B88A5B49, 88E13057B32709C9E90495C64F2C784042D4D36212E712D85FF50CF5D7A4F55, CDF249CA92598CB6A9A69093C6B56CF6DB5528D47BD65B13E6FA0158533E4CE +1FC4865AFE00A9216B0B5FD32C6300C4BED0707AE4072A03E55299F11DB, 9E99F02084324394D6B8B55DA6149FC7651C7783D203653390CE34541769EA40, 9B47F28311FB4D7234C5075FF33156A2BB16A56EC9A28502FF639D916B6B47A4 +5F4D9310FA01FB6441221F798529024E3C715170AC157E0BAFF7CDD3591, BA3E7809446345534205F2391B7B5AB9A94C0C5AFA1E6386325603E82EDBDA14, 6ADB39D39304441162ECA57EAA989CDFE66ACAA57C8E52CE6CEDBA9743C88BAD +11DE8B932EE05F22CC3665E6C8F7B06EAB553F45204407A230FE7697A0B3, E208B4D9992836520F7D8E29B04A7BD5AA2290D9CF8624241332D8DAFD1EAE0F, FA82D6C93D0D1DAB057C472E6F37C5EF4D1001FE714AF333C4130518069765C4 +359BA2B98CA11D6864A331B45AE7114C01FFBDCF60CC16E692FB63C6E219, C11B3277A3CEEF5DA8076D4677AF5A6618983514384385A4D98B2F06A2D7C91D, C5E4896A6AD853B0327FF00D164500412C4725CD70C76EE4A019A5860A14AA0 +A0D2E82CA5E358392DE9951D10B533E405FF396E226444B3B8F22B54A64B, 7CC8415D948C45A8AA146EDA4D3BDE104035CC4AA88B770BA4230878AF96FB9, EB12BC83D2D0B8874998678233BE7AA150FE5E577A7E21ECBAF3621D8022C043 +1E278B885F1AA08AB89BCBF57321F9BAC11FDAC4A672CCE1B2AD681FDF2E1, 608F68DD21C91F8B2D60388F28298466E5DFC823941DFA36E82A89F7EECC0C83, 3E69CED4D5E7016D85B4FE8C395DD683A17AB1DE8DFB5B0EAE99324381434319 +5A76A2991D4FE1A029D363E05965ED30435F904DF35866A51808385F9D8A3, 5F20FB3CD1A60A72096B5932010020953FB7797675FB004D12CE3F2668B237FC, 580330874D2DCEC31074B96A8F26F4ED59BFFF8DCEABC4DD1600DE788267141B +10F63E7CB57EFA4E07D7A2BA10C31C790CA1EB0E9DA0933EF4818A91ED89E9, 5BA663EAEE267270A730AF486728AE610FD9AA3315E066954AD67FB6E5598CEF, 8353116470785D5820A3E5E65BF7168D0CFECB07CB08E091B219A39561373F4F +32E2BB76207CEEEA1786E82E3249556B25E5C12BD8E1B9BCDD849FB5C89DBB, EEC197B6293DB3F1ECEB284B8FE8F4DCEC82064C18F04A2F1C5F9FEB94E55F0F, DB514A0FB0A517D28293D22D243A966099C24093FE60F4E8F9D829FB50AA3B39 +98A832626176CCBE4694B88A96DC004171B143838AA52D36988DDF2159D931, F654043977C77E6F191FDC445204BEE57DEF6714BB27E6EBAAF7D9E01C1CD8FD, FB07FC259743372108255E5A7F0393442C528449CE84C4BC6CD0727AA9F622BB +1C9F897272464663AD3BE299FC49400C45513CA8A9FEF87A3C9A99D640D8B93, 73B4826E1C9B2AE3CF8643DAA6FB7795BDD86679D1A47C70D9AC20883BF8D8CA, B2E05B67A6CCD2A7444B190A9D031597218D1143A0585B085C0BB8C5FA0F4F2A +55DE9C5756D2D32B07B3A7CDF4DBC024CFF3B5F9FDFCE96EB5CFCD82C28A2B9, 8D23774399E176148D11368EAF797D8E3765BAB70B95BF5220EDF2A2E71DBB53, 10C497BDB0E551D849EA8CC47572A4455D1F76EA16924BD8D81AAAAA268FF013 +1019BD50604787981171AF769DE93406E6FDB21EDF9F6BC4C216F6888479E82B, B7C7C79C871A59A802C3A40806C7B6DC3611A16DB857DA0A550E50334CB55805, 334F59E172D604466EE4E00A4CD8F7EFDC528D7E43B460D6825CC88BD37858C9 +304D37F120D696C834550E63D9BB9C14B4F9165C9EDE434E4644E3998D6DB881, 9F9C87D64EA3C8017BED071C909893CCC347DCA0CB62A66045CB4F02918FC974, FE8B4CE1D9BF7690B5F91E30687131A7899838F165CD15CEC51013315A31286A +90E7A7D36283C4589CFF2B2B8D32D43E1EEB4315DC9AC9EAD2CEAACCA8492983, 4DAE1D93D43579C44E4DF5F63AD4422DDB1E0E0920D72D9CF0DC1A45D3539509, D04847FD9C23BD4C801FB7F15578F948D1A39BCB1C8FA11E5A3E8E6CB87263C7 1.3.132.0.34 1, AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7, 3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F 3, 77A41D4606FFA1464793C7E5FDC7D98CB9D3910202DCD06BEA4F240D3566DA6B408BBAE5026580D02D7E5C70500C831, C995F7CA0B0C42837D0BBE9602A9FC998520B41C85115AA5F7684C0EDC111EACC24ABD6BE4B5D298B65F28600A2F1DF1 From 730ab7423898aa5dfcd634ee191b2cc66030aa0a Mon Sep 17 00:00:00 2001 From: Karel Miko Date: Tue, 21 Apr 2026 22:01:56 +0200 Subject: [PATCH 8/9] avoid segfault in ecc_sm2_test --- tests/ecc_sm2_test.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/ecc_sm2_test.c b/tests/ecc_sm2_test.c index 9c55a3f08..8940e027c 100644 --- a/tests/ecc_sm2_test.c +++ b/tests/ecc_sm2_test.c @@ -153,6 +153,7 @@ int ecc_sm2_test(void) ecc_key privkey = { 0 }, pubkey = { 0 }, draft_pubkey = { 0 }, draft_privkey = { 0 }, openssl_pubkey = { 0 }; int err, stat, hash_idx, prng_idx; + if (ltc_mp.name == NULL) return CRYPT_NOP; hash_idx = find_hash("sm3"); if (hash_idx < 0) return CRYPT_NOP; prng_idx = find_prng("yarrow"); From 1e931b1518a434788974df5c7132b7cc56084760 Mon Sep 17 00:00:00 2001 From: Karel Miko Date: Tue, 21 Apr 2026 22:17:52 +0200 Subject: [PATCH 9/9] remove dead code (Clang Static Analyzer warning) --- src/pk/ecc/ecc_sm2.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/pk/ecc/ecc_sm2.c b/src/pk/ecc/ecc_sm2.c index 761a811a3..d53ba30eb 100644 --- a/src/pk/ecc/ecc_sm2.c +++ b/src/pk/ecc/ecc_sm2.c @@ -304,7 +304,6 @@ static int s_ecc_sign_hash_sm2(const unsigned char *in, unsigned long inlen, modular inverse is blinded with random b */ - err = CRYPT_ERROR; have_pubkey = 0; for (max_iterations = LTC_PK_MAX_RETRIES; max_iterations > 0; max_iterations--) { if ((err = ecc_copy_curve(key, &pubkey)) != CRYPT_OK) goto cleanup; @@ -562,7 +561,6 @@ int ecc_encrypt_key_sm2(const unsigned char *in, unsigned long inlen, } /* C1 = scalmult(k, G), (x2, y2) = scalmult(k, PB), mask = KDF(x2 || y2) */ - err = CRYPT_ERROR; have_pubkey = 0; for (max_iterations = LTC_PK_MAX_RETRIES; max_iterations > 0; max_iterations--) { unsigned long tmplen = c1len;