From 75087469f7ff3f127538aa51fbafa6551890978a Mon Sep 17 00:00:00 2001 From: Ron Eldor Date: Wed, 13 Sep 2017 14:01:31 +0300 Subject: [PATCH 01/29] Add the Cryptocell library Add the latest cryptocell library, and add support for CC310 lirary on latest Mbed OS code --- .../TOOLCHAIN_ARM/cc_310_ext.ar | Bin 0 -> 42702 bytes .../TOOLCHAIN_ARM/cc_310_trng.ar | Bin 0 -> 9230 bytes .../TOOLCHAIN_GCC_ARM/libcc_310_ext.a | Bin 0 -> 11546 bytes .../TOOLCHAIN_GCC_ARM/libcc_310_trng.a | Bin 0 -> 2670 bytes .../binaries/TOOLCHAIN_ARM/cc_310_core.ar | Bin 0 -> 497664 bytes .../TOOLCHAIN_GCC_ARM/libcc_310_core.a | Bin 0 -> 287272 bytes .../include/ccsw_crys_rsa_shared_types.h | 144 ++++ .../include/crys_aesccm.h | 315 +++++++++ .../include/crys_aesccm_error.h | 134 ++++ .../include/crys_chacha.h | 234 +++++++ .../include/crys_chacha_error.h | 103 +++ .../include/crys_chacha_poly.h | 95 +++ .../include/crys_chacha_poly_error.h | 95 +++ .../TARGET_CRYPTOCELL310/include/crys_dh.h | 446 +++++++++++++ .../include/crys_dh_error.h | 158 +++++ .../TARGET_CRYPTOCELL310/include/crys_dh_kg.h | 203 ++++++ .../include/crys_ec_edw_api.h | 201 ++++++ .../include/crys_ec_mont_api.h | 213 ++++++ .../include/crys_ec_mont_edw_error.h | 114 ++++ .../include/crys_ecpki_build.h | 207 ++++++ .../include/crys_ecpki_dh.h | 90 +++ .../include/crys_ecpki_ecdsa.h | 139 ++++ .../include/crys_ecpki_error.h | 303 +++++++++ .../include/crys_ecpki_kg.h | 88 +++ .../include/crys_ecpki_types.h | 478 ++++++++++++++ .../TARGET_CRYPTOCELL310/include/crys_error.h | 273 ++++++++ .../TARGET_CRYPTOCELL310/include/crys_hash.h | 285 ++++++++ .../include/crys_hash_defs.h | 66 ++ .../include/crys_hash_error.h | 108 +++ .../TARGET_CRYPTOCELL310/include/crys_hkdf.h | 124 ++++ .../include/crys_hkdf_error.h | 91 +++ .../TARGET_CRYPTOCELL310/include/crys_hmac.h | 214 ++++++ .../include/crys_hmac_defs.h | 64 ++ .../include/crys_hmac_error.h | 108 +++ .../TARGET_CRYPTOCELL310/include/crys_kdf.h | 211 ++++++ .../include/crys_kdf_error.h | 105 +++ .../include/crys_pka_defs_hw.h | 128 ++++ .../TARGET_CRYPTOCELL310/include/crys_poly.h | 107 +++ .../include/crys_poly_error.h | 89 +++ .../TARGET_CRYPTOCELL310/include/crys_rnd.h | 380 +++++++++++ .../include/crys_rnd_error.h | 153 +++++ .../include/crys_rsa_build.h | 152 +++++ .../include/crys_rsa_error.h | 277 ++++++++ .../include/crys_rsa_kg.h | 129 ++++ .../include/crys_rsa_prim.h | 125 ++++ .../include/crys_rsa_schemes.h | 521 +++++++++++++++ .../include/crys_rsa_types.h | 616 ++++++++++++++++++ .../TARGET_CRYPTOCELL310/include/crys_srp.h | 375 +++++++++++ .../include/crys_srp_error.h | 91 +++ .../include/driver_defs.h | 354 ++++++++++ .../TARGET_CRYPTOCELL310/include/sns_silib.h | 113 ++++ .../TARGET_CRYPTOCELL310/include/ssi_aes.h | 325 +++++++++ .../include/ssi_aes_defs.h | 83 +++ .../include/ssi_aes_error.h | 133 ++++ .../include/ssi_pal_trng.h | 66 ++ .../include/ssi_pal_types.h | 115 ++++ .../include/ssi_pal_types_plat.h | 57 ++ platform/mbed_sdk_boot.c | 27 +- rtos/TARGET_CORTEX/mbed_boot.c | 23 + targets/targets.json | 3 + 60 files changed, 9850 insertions(+), 1 deletion(-) create mode 100644 features/mbedtls/targets/TARGET_CRYPTOCELL310/TARGET_NRF52840_DK/TOOLCHAIN_ARM/cc_310_ext.ar create mode 100644 features/mbedtls/targets/TARGET_CRYPTOCELL310/TARGET_NRF52840_DK/TOOLCHAIN_ARM/cc_310_trng.ar create mode 100644 features/mbedtls/targets/TARGET_CRYPTOCELL310/TARGET_NRF52840_DK/TOOLCHAIN_GCC_ARM/libcc_310_ext.a create mode 100644 features/mbedtls/targets/TARGET_CRYPTOCELL310/TARGET_NRF52840_DK/TOOLCHAIN_GCC_ARM/libcc_310_trng.a create mode 100644 features/mbedtls/targets/TARGET_CRYPTOCELL310/binaries/TOOLCHAIN_ARM/cc_310_core.ar create mode 100644 features/mbedtls/targets/TARGET_CRYPTOCELL310/binaries/TOOLCHAIN_GCC_ARM/libcc_310_core.a create mode 100644 features/mbedtls/targets/TARGET_CRYPTOCELL310/include/ccsw_crys_rsa_shared_types.h create mode 100644 features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_aesccm.h create mode 100644 features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_aesccm_error.h create mode 100644 features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_chacha.h create mode 100644 features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_chacha_error.h create mode 100644 features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_chacha_poly.h create mode 100644 features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_chacha_poly_error.h create mode 100644 features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_dh.h create mode 100644 features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_dh_error.h create mode 100644 features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_dh_kg.h create mode 100644 features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_ec_edw_api.h create mode 100644 features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_ec_mont_api.h create mode 100644 features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_ec_mont_edw_error.h create mode 100644 features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_ecpki_build.h create mode 100644 features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_ecpki_dh.h create mode 100644 features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_ecpki_ecdsa.h create mode 100644 features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_ecpki_error.h create mode 100644 features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_ecpki_kg.h create mode 100644 features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_ecpki_types.h create mode 100644 features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_error.h create mode 100644 features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_hash.h create mode 100644 features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_hash_defs.h create mode 100644 features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_hash_error.h create mode 100644 features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_hkdf.h create mode 100644 features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_hkdf_error.h create mode 100644 features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_hmac.h create mode 100644 features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_hmac_defs.h create mode 100644 features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_hmac_error.h create mode 100644 features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_kdf.h create mode 100644 features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_kdf_error.h create mode 100644 features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_pka_defs_hw.h create mode 100644 features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_poly.h create mode 100644 features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_poly_error.h create mode 100644 features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_rnd.h create mode 100644 features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_rnd_error.h create mode 100644 features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_rsa_build.h create mode 100644 features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_rsa_error.h create mode 100644 features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_rsa_kg.h create mode 100644 features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_rsa_prim.h create mode 100644 features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_rsa_schemes.h create mode 100644 features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_rsa_types.h create mode 100644 features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_srp.h create mode 100644 features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_srp_error.h create mode 100644 features/mbedtls/targets/TARGET_CRYPTOCELL310/include/driver_defs.h create mode 100644 features/mbedtls/targets/TARGET_CRYPTOCELL310/include/sns_silib.h create mode 100644 features/mbedtls/targets/TARGET_CRYPTOCELL310/include/ssi_aes.h create mode 100644 features/mbedtls/targets/TARGET_CRYPTOCELL310/include/ssi_aes_defs.h create mode 100644 features/mbedtls/targets/TARGET_CRYPTOCELL310/include/ssi_aes_error.h create mode 100644 features/mbedtls/targets/TARGET_CRYPTOCELL310/include/ssi_pal_trng.h create mode 100644 features/mbedtls/targets/TARGET_CRYPTOCELL310/include/ssi_pal_types.h create mode 100644 features/mbedtls/targets/TARGET_CRYPTOCELL310/include/ssi_pal_types_plat.h diff --git a/features/mbedtls/targets/TARGET_CRYPTOCELL310/TARGET_NRF52840_DK/TOOLCHAIN_ARM/cc_310_ext.ar b/features/mbedtls/targets/TARGET_CRYPTOCELL310/TARGET_NRF52840_DK/TOOLCHAIN_ARM/cc_310_ext.ar new file mode 100644 index 0000000000000000000000000000000000000000..07f546ccf250e79943c48c60d7f0204ccd1a7f79 GIT binary patch literal 42702 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 literal 0 HcmV?d00001 diff --git a/features/mbedtls/targets/TARGET_CRYPTOCELL310/TARGET_NRF52840_DK/TOOLCHAIN_ARM/cc_310_trng.ar b/features/mbedtls/targets/TARGET_CRYPTOCELL310/TARGET_NRF52840_DK/TOOLCHAIN_ARM/cc_310_trng.ar new file mode 100644 index 0000000000000000000000000000000000000000..e1e34ce8100c277f92fb5121bff231148c54e335 GIT binary patch literal 9230 zcmeHNU5p!76~1G8cb!dAHk+m;6`P*adSw&VRtl&zSxXV&ie509O0Ddq0$c(R_v z_Bb=Me^Et?lolQkLZ}f1BvkRn8!M5=N+9vjC)5WXcmPD-;EhU1jqGoJB|y_=+Q zMwJkIr91bYpL^!qd(WM{=kv~7RZO+{(j?CgmV}S&_5Dwlz1&w=nMo-=W3;a7Mik$RD>8Aj_0tC($7WnW7-F3lya3{voV#8 z8P0$hu=&B6vY^x5T+A4zt?k5$X`n6J)K!~qD`rRUY*=h8ALrr0H;uN&o8Vllkx25} zhIx|*d(_&Fsp_R63#v<5;vm9*D1Z@-SX^ri`!p1!-L7TM9F1Xmgy^QGY;O8+A zBYf91Zt%{{XB2z=`$o2youxTJ&QWnSQ>bUfEE~&aS81mDs!UhJSC_>SEefkt&VNH( z1W_Shs})2_#Zopelz;(a3+2)>R-h<_Ya`9dlsW`n(6EOFGgPh$MVg0!RWVbeLM9{1 zG6-ckPc!9`lwYPbyf_!jS#c3A8_uX6KVOEcbiGn3S8I-gIK-uCWksNKX_}nF5rsnD zad)XMNj;wvJIMqT_dQ?;deSTOnpg$Jm&;Y0lt<@F19U~GWpXHY76aeYcix#wZw8LP zsFa~O$F7_&mlhK{624O`2}`hCf+*8$H4iUcOad2|<6vUB6>l!i+?>sja{`@BrhI~t zE+=rq=v@;AuiYw1z+HbIO4zxnf0cyZcxw7IU{&$J4&P*ZtV*KpP>S?El3_6Ua#Z=%d3x=X^8)ecneiVBr~{F^|D_O^29) zoaXruAq&6{jS+GcTg=Pi5PNaOhWufD)7C5!hg8B=)}d{BJyUDN8`}Ej2EC5y8i;n= zjtc(ihO~#oF=V%{YqY5;4b3ER$V+TO3i>+7Rkd52nq_kw=(O~8^1$@3cM3MlF7>~R znox=xrlbTg@V;xZZQXL)4&^hEJQ=nOL*dOGwh^Lgex^BnV~ z@bk>)Kp8fXFcZ+3_9wAGKdjV2i0b3666U)87=>_giU?1?S&YF*PvktkKE{+^uK@Jl zP97+FvKNN*(r`$!2WovA=#S?Eig!ToEoh@q(Pw<`6x0h)PeAp`eb7Tbgt?=GdN}4h zR1A5qL{Ag)nnytE`F95TemxcRcu(llLl)?Dp>fKO;Jo|Kr#A$%cevcsZcDKTaEjRn z;1u)eg&x52Xq@5?I8m4?t`z|c<0Q=V&3oj_rzCQhxf{A0nF-(h&Haz27yvz*(*D2x zvp-HkAARwC?2(^*yvF?Of)aXfO$q<>7Yeh-%!Kzs7tUwMUW8>blY3E?{FOlOcYkNj zMShi#x*y!XcS;(U&PnBe>?fbip_Qq559v|Z|Pl&!B z<1vqY&ps00aRV_>jOQ4SdCVV|hQ6`KcuWtU`G3J<1~Q?C0V)%ri9>+OgafF20dM$j z`6jf&*_}I)x5Mv*e!$#3`vxJN9A#G>`RzMnZ%5tkkfM5LN0X!TgcN*mwpRdNT|PuE#%Tabon1b8-g6y z!H^&UNB={RT(4paG|ms{kuW6$nH<>Yk?7LVxRRw7_yMm!ATk`ZJsX8x6U|d)G@q!*S}D8k{L~1hFW@ z;_$r)&mcB~Jg?N?41Em<#HY{}>P4Xr<5=&49t-?O;aI;0JqmhW@%$UcvCaZgxa$c) T+3RBK$FaT-PUk#hKE3|}rkkaf literal 0 HcmV?d00001 diff --git a/features/mbedtls/targets/TARGET_CRYPTOCELL310/TARGET_NRF52840_DK/TOOLCHAIN_GCC_ARM/libcc_310_ext.a b/features/mbedtls/targets/TARGET_CRYPTOCELL310/TARGET_NRF52840_DK/TOOLCHAIN_GCC_ARM/libcc_310_ext.a new file mode 100644 index 0000000000000000000000000000000000000000..68b3dce450cfca34fcf0235e07673a16c9c2b91a GIT binary patch literal 11546 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 F_Yc_1l5hY3 literal 0 HcmV?d00001 diff --git a/features/mbedtls/targets/TARGET_CRYPTOCELL310/binaries/TOOLCHAIN_ARM/cc_310_core.ar b/features/mbedtls/targets/TARGET_CRYPTOCELL310/binaries/TOOLCHAIN_ARM/cc_310_core.ar new file mode 100644 index 0000000000000000000000000000000000000000..d6db74847aeaba344eee6b21a1079dfe48f1576f GIT binary patch literal 497664 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ƌc{ug=A$}i%V#(y3{zZiI^11BUkcJbQqb%yo& z4PkY1OF`=O5kpI|-A;tuLz zzKVQ@~G-;9j=`KTjK+>$deUEgiP^x)x)H;OA+R zKSRM*If2FE-%rn@;$m6uk0T!&5?3t`IjRads_KYa4g4Gp{L()xWOg)UcC=$kMy(k^ zT>CO)cC_N3)6#8|DMVjuDl5uvzQmv5t!HPxz5KG(72;ThI946<+tlvTuCA)YYMi^c zw5)h2RR1nyE=wgLj#Y?b^)GU)+W%T!M86HbB!@xmhm{wRhki5BZ?Yc>AH4ha zibwu*a^SOt%NMSgJnrr+w{7W=V|_h))^C6Q;hxW!zI^xGoL)sSGvD9#_ecJE;jfYg zPD_Qxf8d(hp-<{Z@-L>A3~gQ2Dk9}uxK0sAmn|n;TM~RLt<3fvmC@jNFDe==sFz2_ zbi(OBgUX;bXbf6|&JbqM8w`eULxdsH5M_Wq6WB`rp!|I-N9q;bCZ3yCf$3ME3b>`5 zN;uC8`asFPDgE}91M%PrWWea@i9-( zRbUoI;y*pta*&^a*@#fCQCg338s(L*rv&A*0(Vn9jB*_^e+o;Tg_+1h&x#!6`hw31 z=YrpxE@uLj>kH;jZ9%>Uq=QY&_Cu3}lRq3pzQuAPV&zMs$X6+6`~@1d$v}}$w#WzDIqa;k zpFcIKZT{4#q@)h(TsDArhT!K_hQ9;_Gd67@oqYmV~;*x@v|#ydwj z3n#)RXMXr0>p;C*)ts5)d6eNCj_1uae82$B5xBr|<4A@K{h)od;} z3HyuRrF2E@;daAA`Ch@$-L=d4r1Jr1md!da+WmXf9C^evINUAQ5-%pPv&V$#yfN8? z{06o7a_&Jb5%*p<@tDuDy*GN9(`+*2G+V!8?o2bGux8Q(RbHL6o1juB@;4-IxC*%@ddQSI(u@F&=peEDwoV63ntXi%TtqZQmTr0rBqtI|Fy|ZN1(s0Ni>X<%V z7uz>Yoozy&zr(I&lHaanv^(sy3EFLwaL+SE6|*a;6EyBZ0hS|;V++ipg^gyS_)!zq z5!r;K55iB+M+{hnAzinSu3Jdg?Vsb|R96)d=QO12)}e*dnl}~V999=zBKM;8V1_t{ zm$(Y?jh@bJht64FR_12NEM&)2Lqq4R|8Kgu$F74%#BUXnehFThnj3yy_`{93N{wC8 zN^Pw-&q3+*+dcRwb^=d-477};FKMkRhxj2ppAkQF?_>GeG(cHp=LRTwc0VbVe<&k{ z_;yNNIQkV`g!Cu;c~rs;{%iVO4SSIOn&{&6#XSm4d^+ks6`}hizTDlQbcT}dneeTk zkK;r4NVo*F3kuM^5S|7q2hyEOlL08^IG+#HSzh=K{Soa0)KXeSVN3LyBs{<{?G%rkMGPj5L-J9r(Yj zO4sIA^dG^?Y`}V#1C})l!8&xukw;FW4DvNS^NQla=KyCrphI^Q&!vmCB>j`?2n^C;7iuOsKeA4R?ca_3Qx zd`VQvqnrdh*KMu^&T-YUI0%8$MQ>f}c{plCnp z1k~A&x&ayes1HyVKe`Gi#*c;q#rn}Gpss#24yceqsc&5$mr{?=(WL*MgoQV z(KMh)hQ7CbH&IpM_BDWS*oYIwf@gqdKTd;RnAj3W_uIysqR2sf*&|?rFv!UDE*n^be>UH!j!;FGD%r_2Ifx>kWoe>-B@hiSUXe zd0x^A*SS;rzRzt=zPFwDuYFA_2icwc&}R||8=Y@u4Ieq!lUOo>{4c2n7R-c~CHUEC zwpy+5&18dbrWA0MWqz$z=;prOr|mOQOujkA+gO=gFw^hnDMge#Gew>X7bbF_Na3e4 zRf&v?DtX?~H?Y&kchU*xI?=Fgm3W16Jqfq{@M=1JSglwUr_Tbltcp#T&z4oO6{uxZ zJPp*cD)s@jtco{)T2{q}K>k&6$*XrdYEjGU=iCiI8b7iFNuG=7`B(^~V`+ltN)N>> zMoe#i?%RO+FciFIBwjx(Yh%sK!J28_VDzsPS~JqwZ<8pknGFp_)3K9Xw_YKB;M-iF zbwr%PHyo@QmBVoApkTG=90KTGLG8$cZzZiMg7L$(!V33R5+61DR1v3i!X|LWjXqT$ zRr7VKlxC|+RjD7V2iKl)_A1Rn3JUhYNSJme< z*G9(q(~_^$IF6lE8E5lz>VI}?>TOO#{mxT5l`8$%Nwu0*saAN=O}V7&y;#*|zN$^z zDGu+VxGrLtgRX_d{_gP8CF&742d}xCVpNz3?Qc|D={kB+&xt+QDSbh;5I4ryjok!XR;#w{a0Xn)QyTPw8pE$Wp5toMoxCCgD`NdS7bPyM|L4!WdB+ zLp`pA0fHmKQzCrRggltF3_(sy*SE|Yjkn93u*+GE{P0zFYTe`FfU{ zjU1mrmCKuzi#4diZmwZ{K6X-@gmL7naVk>el}n>4-4|IS2tW70Txl=+$oAnx$qqux z2)lfHj1v05S7&VWIgD1b>Xg`}(YM9uBI^!3mF#M~6@;V#p7k{6Y}6uY zZ-iA{3!5)7vfJ|Db1p&;VP1tmnotfvZ%5HOXbI z*m;idx2fv|x<4)J8=iE$M{6<1^pxxHluKUmu!f#Lc2c7j;;-d_t#+xcmeqb`(+KQ8jjE`J>D!t$C92M9?rLf5H=6BJ6!+81DCKXV zA@O8LJlP@sexPn>=wL%gJlVk$F|8$PA@O8&NIVJqwAD+878Q*cZW%iK>fu*gt{$G0 z{6ogb@x}_7fiAy%?h~bN0GCxv{u5LgI@l0013fgI2^DfDrL@?vW)`g_L)Oe}HH=on z&b19WRunK{|xEXzc)WSx%Q_ z@<$C%QY2h%DLz?&zI5qi0{u+jVY5n-PPQ__f%HU0o`bk<&$XTUhS;Sho_8uFa^}eTt6|;ciHG^HCst66tb?LE6hfSZVc} z($@y1R|nzZAeEvgxKhY~BSrpM!j&nIB`8dUs z9GvJaoYry5_mnhf|uzh%3th#DmyU4&_UN5nzCPZUZH#YA!cHAK<= zYEB)TKFH}VPWN&88mI4bdYsd*IVFJ^)fdev`B)=7h|^?FMNY|Y8l}(Ww1(5woH{tI zC)x|^j3~zAc}~w0#kiQXpqSJ#L~*|}I4vd$A7slpts@$Xy@6=FAZ#Owaoj-^KEy@O(+XmG!l4n#4pe;|r^eT~!iiK4#aoPN#e_ndae zo)pmoJ2_G08_j7tr*kGn%{qk|z18bbxPaukP3sI6Ab2^hKs64Uk3BYpJvsmBNA)^Px$$oVa-@p4xVFx*cXaE353) z)zlQLC#AS}+R}=aYLv#Ne$)gN`-aNCIZm%EF0A41Jy`_Zhon-&pyZsPB|^GN%b5&^ zqWMt7xxS*RxH_$3ae0lsDgz@@R8zXdo>zK{J+nNuw5AOP`NRh7O>)rki&i>4$Rnpw7WrDlHPt7F&ynvd zyr<+Krwu@ad`)TZV=uNSBIL_pogM@By?xK7U&yl)U%>Ga%r3iAg}f1iSR4XH85_QHXXhOo}ZNJ)##97 z5$^d&>Tm9z$${7zgr5n*JA-h#w>I`kn}&MECBC><%cGOhyc=T!;~qlXrl7dr*wld~ zO{7`m+q)(!-7AbIN-1{YZdjMm&a&m@OH99cv_Uu6XD{ThKE}MLHT44Mt zjDKLv1KNu046o*zYbYn5L$p$PQ%)eh4|A=)rU>POa~5V(N?`6A5Vz)vz_?jxXH9IH zH%uQGKP{-GDM2_p2u}*a8Q$7%6Kp!_KOcScKR4ZG^{(m?5NEU^Zgo)HSj<~ME{pGF zI!T+5g(nTqTsoe#xGX$@PaX4FJ$UvS*nB9SIJAZ*t^__r!p5SeRw?zhHg9+vDbmx^ z8BY&NDMr3$j`f-e-iV+P9q6eQdJLouqE;}N8-*ydFx=p%6`<#WyRNM?I1uL$tjLoq zn5`-B6Jf^naHF}=guGV4A><<6Vg$vt8NMS_21kzf_6ZlWCwQY<&Hpo)Z{6q%tya)^ ztiCnf(PPDmd_a4;ow@xYXs%8M;S)jl(;!T9`*EweJ=(_H9%*B454W1zDJPcg)optm zPlsj{>NZ-NwKM)l@(9B3hrHwT(PVg6#ilhU%z!=t-zO;kc5RwhJ0cD1Dy3PQ7oclk zc`-8s-bEsr2NAzcjpZ(Q7SRq*!KzD-pwNR+0mkRU3am$$ArMuLVK+aUR3B_45>(Kc?L}NTB}!Q!E-=q zDFJClTIFYQHbO@c`U+$8j{VNe-sWbN?zerz>r1QV9WWBs0AvY3rfFg~Pe9BM<`xoe3eqzw3Bpq*HYNqs zXDSTJ5jh~I*%+DA9FBAFhVY2~H+g0S<(LtK^Az~8riGr!_=q@J=SO)>;}kGT(9~Ni z2z?BRd51p!TxixBqWUD>v29o9xF}O6^L?HxOkK_0;vVtP|F=$Rp}!azALfwihThWr zl^)V$5fXZNy2N1xINmy`sfvYfC!Ld8UEzr_bs=O_?~06H`+1{5E-C5NOcQ_G_o??3 zB~8fN@YYGy`p)suah+K7#h{LR!@;yc~W&m>=i@Q@_-_pN+%osuTjsum*32~Vsnco!mLtNGTyhzTS6)BRG{{5xaHvHk zjk>aymzppmm>(@$TYBLcHVf1rof>n2IZ*cJK$F@(9tP)j+qa+j`%d-Ks#|wOJm!&W z^Gd5O!X?~`6eF!Yc`X>~kA2pi%~&_gSl76(o1k-yT}hAcys@*pZ#(9*HT+sESl|$& zMZC3!u5f9f1Ex2TE+5_Dnu)97-Hdhsm8>ahS;@SUwczDJSbI7VdShKo0@EYYp0)wS za8xm|s#SgEt;+8~iLUcKYAMIN(Q5S?lJt&W+NNivdIgOs zP{-9WgL|OzzduY<@jcey-{AyLvPbf3HW~4l>;Rq2PN$>7qv9juBG9*upLZ5w<6>}^ zzxrG+Tp8aht|!-Z>{h=nRXCy(7xpdbLi_tKeJ0avXvV!^RX3~DuUY4w$rn_K*yR(4 zxHO4N+)sHD@zjJjM0_?JZ`chnL4Af;ImNr4dEsj5^+3fAO4_3RgYaxmju)zM6H#B6 zgpw|S-@lCddaHMRm*ChdG6UaVT@^UNqru+OxTyDV+L>xqlJ0M#Han%UYj$R>S{UA_ z#?doP?>a$asS^Y-QxGO*Hfpjn1?^N^t8qO(r7?DVrp1GAbH?ZK-V7W5rcD*pGrUQ{ zJ0~pcyZCVM*uBO^kH)T6G{$%K>mBBUQF+3pN*sjo9N~KYw5D^a>p9!?P0zJCmb=>+ z%ijf!-7W>5Nl$6Ka6fjHq${vvMmfUnGRB8{BF*4w-XFzw8)H0+$Bv^aZt2&yrYlXo z%su0J@X~Lc3^P(b%BAdoUDL%TJ?asxBVZGT&Xllsl<7RaN71(-)yR#RQE3}9*{{%+ zUsTq0SpmPOtgD0Y${@Tv2;Urpm*96(E&ZNTw6RuOHJN^SrFnH>Na5e#=vU@Kd`GPn z1LI05u6tmdeRAuvg>A&)ci5;oS?rgmRoHTz|7x5`zXBC_dJvu(gx$V9Jh$6dXFYI6 z7@6*zm=#aI{aR|VOrSeWN1WnL)7pqbZ9E5Rv%Gpn7;&pph`%Q_(xui&-v$$=q89#b z5TjyR_OdGet0v#xV<*GJ1Wmek{S{Yd4M^)1{QHvqdJp@7Z+IKcPRYFgAMGp2D9%;q@n|GNeNr(xLq?)uB~<4Zk!iKNkF2 zXv>PWUZq#-+p(gZKtC~f_y!_kvJBLg?kyCDSfD)1@kxojWvyRvk+y=R1-2pU>&}5z5ozDG~1zK5-_?(sYui`Mrr)d50%QQ>IrcFr`0(yOq-q1IvN*jnfsF^o<8AFzFk22d1cR@K22^s0a(+;zO&9 z@Rvwi%2yTP4}m}CD}?Z?znK{Sg~(hsEkF2c|g zEJt5SZ|@FHj}t}yIP{t57^0|GDS)KX&I*va=MGteVo3= zX?7IKp&bk6oci?=D77~YV?^=Gi9+x4Zlchkc@uL%`N}XZYFt+mMcNjQ>p9-T@$(!X z<=DfqkK^w+?m_DT_4Ou-`fMC$aa_r94aeI#evIRnIBw+l-=deO&_RTvAT;E%?aOMQ zsW-Wr>BB*NuWd(>OrfoVdVZI#NC+R6OYBuODf7yca;u8`%7nQUP;;DCfoQR?x~7e2 ze-zXXGnUn$EdKi=(<>IwEklGdPRht5Ln?Trf*0`m|M}JM+SJ4Ajptep@+&7;4=)#a zUMSo0PdVzEj@#C%#QOljuZQ<<@lT0GFT1B?russj zDMOwqJ9rL1WWd3HzC2`KzT95cF*C|-dYlU}pQ}U6=MeKb#C-k{lO4oz4>6xZ%;*17 z=CdTK3H&}@)M0;=z23X(&Vr#cUVrwhCKCe^sWL`slIe9^bv`uM5vj zowBs{p=Q%`k@-W30!XZlsImp*at-kb7o`OV|IcYKq!?47MQ9J^`% z=-~^-MXuf6Ik!6U@$t@cy(;fmS3EoGdfiJKEcQp@wv2!M?R#H2dux94?>3*Ey+1qR zv(68Ne|N_VQ>qh_ulmPrXAj!v+wYF}cHFND`8mh{2K3r9b?Vet6r zMSqNXVC8XP<1e~vzj*vt;~!nS?_l9wH@$fH|AoaTJaTyd)7z|P<_dR?Kc<~G>$zD& zD(gO3s@Yu@|LO-f&f7M^Iqb8S3JaRLg?}*e?lWKB@Z={KX72r4?UHf#eH%Zvd{@eV zA+M^UlO9fRjOlgPBd>pOZhzBXo_zE6Ws4qtK55YJqkF~_7u}ov=GAkSJNmy{e#7Yg z5#xI#&Kyy*;f^^I-g+Hp9YY`24o%wj$AgPUJhcCX@W?}{ zX=84gS@?bN)4txn=z3=8_~~yAu^RuYYLZfbao#Ts19!ad;2!q<5cm{jGn>HIIsW&8ednm#$uObHV#Z&L3Iy;m+-w z&Np@2Gi2tlz90PIwK*?LyfOOiw8ZR(|FkCmvA=Z7xTBL{SJQ|dxBWspu1q`op{(Sc zqhEj2x8NBuKYGTLp6A8-}k@1 z>*gC`_h_mO`JeSUS~4th-IMhRmA=;xT>r$F%n9AzzGwe~)x9p5M&0uK;j7k&r{9_J z(T;JZVO^5mDBPL+adYQk-lW8@v&t5|SG(@{=m~$jx7+^=_}n#NX6&Y_^Kp0Pzo9?& z`@WyvyQpB`@`DTZb*+l(Uw!1r*ky73b5`7c-g+$OyQ#}AIEHIZ+&1Id$UZYxue;DI z^@`H6cdjix6gDR3+MySct(&u&bTNCD-R^7r;-0_Wa?{&G{ucez$n=K}ellxi&Hnhk zPdvY5|BUQK_dY&h;k31nzPqrjCg$cYzJ;?+KihxHZ{9yO!?|Yl)~+7G;y&}$*R^-_ zZ2Iow8Am?|OZbQET()i6xnXHoX^(`FPe4RZ3(E(clSn^!C>EG?JZLHuW)>i%hc z(h_&M?f3i7&1O!<8YKQF#BnT)#DC(&%0XW5WCKU$mr~kTeB?C3^7Ry4EAv@_4UkvK zK~9r-(K0*MhCK9K$U&|zm={gF?Q}U4s9aw#FM12|H6R_LHpY*p`i%I{{Skj!4(X7a z(f!i>Q(cs=EnajM@=e>jMIbLB+D%9liyyy!&m zg>C*)E%}%iQ2hFlJw3>0!jp0EyDeVyH6xNc?2Fa}nIwXr7frrslbxzW9nKSIa6Uuj z5=@m7RQNQUtF4G|HJod#(Br>Qp~Zh|MN4{EqLH0g(&+Tzk)67tL~ndd_*n3<;$y^z zY9ssHs~U7TfzxddPT|~#v#*snhqIkD|7%6nP?bwPbc|cFg1lq5roMi+WcPU4ZexAP z?k@E+cdLi$-1}hTd4P*7Jtw%j?x3)aTF=F%Pi>N~SgJjeY8MPR5p?XNQ8iT* zwongsLKv*j8&z?v6(Cnjn~CDbO@iqdoiR!Y6Aj6ZhCc9YP$yoS7?2=P*&Nj++pmDE~ zR|S)J4DEi@WZav`MnF14VSKs4X2dB>>WeA4H|t5mxrUXUj!<7BTsh8k=V8_t?YW~> z^%HbLq+8{A)b@N+9P|Erz?WPk-Ek!DQQ4|AW{KjXX!T*b+nh5EwHT$9c0=+ppYP#* z;yvO<+;xvbG(X*#$KDv%ozCU;%bd5>moT5b5w2`!hI6o3^mMYgoO>C-tmDjQb;GzO z&Ca5yXTi3%a4+>hD-3nN=i96rEH?JpZ%7g~JEYh+_%|+M*F`(%ESX9-MofWU;pNiF zDsMCMJZM*M7ykJ$&P%j*}}$~W>g;8=WvgE`HY&9 zyNaDf8pDVqtw%2cqnBsv*zlkP<;^mWrHRzGF+k7BnrM=`?9 z#%^&MyoR)trcsfeyS7HWjmgwZ$ek);(ilB;E6bhLj0!=Negw!u;7;hv5kZI#QIAr z)7GgCeUt&Z&k7b7(|wdN>7twPAxyld(fAPGcL+Wu_!Qvt2|n#uBd=0VmX1y&AP?nF z1%qfA%YVz-uywli+6|gIoYY8*T`(;o_LkI0u!~r}eaJ`GDX}Zo$|pIf{M(41+q%5J zKNc|LjM z{SH2JIer+|!%@d^jyC{z<8wgyN#}kcA9KRj0}tk7N;m^p4s=$+5`;;YUk;QGuZR9X zm}DSwApAEOfD(Qu2=5QV&j#T~g7BR|m~5QOf$A@o0Vv@qL74c`a-j77G5{s4JR3q- zaeK@bJIw>x(5@p2M)4M+U?RUlw67p|h(aHlI1prmx)&-S8_?u^fZ41jihQ+1!AB+A z`DA-~E03qM50w54r>}4tg}#uj>Rv>Vp1>)yi4I%icMvwgwmVUr>1g2T2Z;6%gu_Jf zPfHgtbMl=pK$vH0IlulWZP4icXqTh#!#-l!>Xpb1))DE3{qI$Y= z+LzPuL=#{upD5a|B8vX3C5rspQ3ctsevBxX=nWk2;kc3G101_JKFl#q6qVN!MR^); z!b3Q=a!hBND7}E=VvZdgZ{fIs<2@XEI6lttzvV1Setx07aBgY-Li@s^vZ|3nURCAv zYI{{4>`0eZl*3tiT47m{9Gim(vZO7n6!NC#<}V|g+EPtL(kT!Ony{O7wOLH>30$ACSOmU|$~n z(TnHOXja+%2DT~1-+)w8N_lZ$Nj{iuluRqL7gn`&Nt&ME>Y4fO`Su!HVRZ>^){gmt zF>ax>8goCnqIhxH;%bVRQCL=5EXAT95^7h(`kyILO(+%;YJ|(<=ccW1hd;OERI<~L z?IJ*S>cD;{2l+Die9i$R$Z3>Uz7}y!^~vEiBs43&@yKbxGSTOar~~`F9OQiC5uu0{ zUV_ZA01+hrqz|==qOD}2y|LfVL?tBWq`D{{w%S(bb87J3qkUYKhsybaWugiALe!D- zIctzF5APc}$oD}M(Uo%i`*=^;WB@AX!>@$=;wsp)uL`u2ojkl9ndtE0qotEPKW-=c z3%V(VOq9;&824(KyhTXVxFzWqe6KUv+QpnV8z9GX9fo|$YHsXv(4ak6QCTY<_U)QN za*cu#8|10skf%mLo*Lmw7PFYNPh}E38dG7qgM8&q5+SKnNwPm7 z@q`=lxk{42=~*8h?zsgr%~ihVR7rjbp^*5ld+bwkiMJp-9Q)J<%u}z$N!M1X_ol|C zcWsTmUna>-nrre~4ZR_!(+l0jZcNS;FT>{1hmY%QS_=qlzBC@5XqgjD0Fj+{Jqxhh9t4 zIKlMirpM81CT~i6s{wW>VQY1aFl}2ONS!*1zw%jBBVG6JzGL^g-OG1t&*fKI&8yh` zDo6EkH^~O&5qi+Aip%nk*Zml;;r=v-qFtFO6Myu@gpb zu*)!X;JenL1CET|J!H4C&E5(bu8`Ob^O(Pg(q)NPl%l0DTw7YwOp_a$UoNqI+ho~0 zZ_-^2UByJF+1VR&v&(E9r2e3X*rmbpas-Y26qR_Bn8;V>8Fwjs$LCb~+c0^VjPXlI z>DGw97Vj2?1gm-Mj%7?vXEkRr=_yIiN4gBdlHRorvm7D0<50F92Dz5hTX!$5x9lFe zo8+&M)fG1OX*85MtmgN8J60`a7ELK-?9RqMuNZV#wS1)|c5-L!RK@Ae9atpCXx(FX zX6^X8ca$f|wvgHN&GRJ~bA1VotGrRFG+Y<=-gD~i&S&0jnI|uvg_d>wDUj}54#rSg zZy#Y!XZh#tuzL!w%b3@0A@MCYtuz@ObeEK95@TIeLW#J9NrQ#Nm)vvwE8zF2dCpVP z{RpPtH6@8`+_2jEiqp1Tfv1F4ot2HsIM>I!-{1Y_ZmU`2k>!&;Xy(}SuAKk=Sk;?V zDUe#fVvzexYog^D=;kg!zq-2?2(qkSNQ_jh3LSE{JO^nfE;e3&2N&_9 zKh>A*zEStWip%KZnT!1|Yn|vLl%p@(E%Pp3?ke$J1znuGxU{TzXkpdDOYCmonfc37 z$*{_*iUq@%#Qaj~D=jZ7TU=}pNn59m!x)In-*f)t%39kewyM- zc>D6!wyoDma!|1T{efgHvivcT$5Pxrd{SYpP9eWcjeTb2OeVlYnw-~#>)*4yH?P&N z3tO+-psmwvgfufXcGt=qB4Te&jT91)PGLQmK$}2QV}tUhATQ$Od`9rU766l#JHNHO z6trF$5qm4dizcK|xCQxAK~rLHTdP^e+ANzG5qld+AW3#h;U(lrM!W4;r`xnrZDYb) zx$U!HVm*j*?e)<_l_J~?Mp`atO6+pk5?@+u+0=;G<*ntP;pl@LNd8H_cUyu=&;a*9 zeNs>{-@GOTru0t~_Jjp{#6qw|pISNc?m_$YSE@}-MABv)RC;4Ln z0Le#b4G@k2cH^4nneg|ZB-5n1B-{*2Hr!~=2peD+C5n2o zIh{=u<;#eo{4$~_&wM?jJlSfaa&Hhtxg(sO;Ph*vD6hsnP&v{gp!{TSiSp-iI)^B= zLlpTQA&P$O;rI|y$PGW_v4*6gao9PmChAf2{Zp`8RI|U^|s2c^oiTb z2`&lpIv_suO9EwqV*3KhK-p(o;>sVFhvH>RVn5#7TkKU8Bv8e`rA(ciKOe%3tBdV( z7thb12f3;}VU+NnDc8H2mc&mY+za?J^7D)L+O)s-Ii7Pl$d~kN<8kwc-Vlh%X%s16 zlN`{154Ii_Ovq>D*F@xe!E!*#cNTk&9OSkJAVR*Tw5~X0Ncs(OkS~MffIA=u^dK<; z8R4FEjf9Q5VzOmSU?b!e2Am<~B`YPr4htYsd2B302tQ+}QBopuX&ql&}Uz=wmM~{XD zKMFrC2ONuc6GFh*NIL7bu3@#9)2tWNj+|x{w6|^t5_DR}_cq4`b*1BiroeGQTiewo zo!=taO0mG~KCQ7FbPur~hE;LaZP->$X3kSb8l20@Hv=lN)@kpTF*~xK^B4YijBS381(!^o8)mS z#ajnYjXhG|mpoD`d__{*sbW7%O887BTaiv*CW_BMdUP>oO@qNCIE>p=CY9q)Hg>-T zeyiV=lOe5gs8oqzt`}^Lef13+$tzXAZ<7YB8Myan{3vUPir&Te8?_=%2y_tEw6KH4J{C0e}XnP@hW z*oq2cGbnkHOccL4K`UxqLj+b7zS=lqu&OkUVf5@^9cgGi)nYy6Ixd7YI4awJ)^ za#e)|ttzX3oyjXNQPi_MojkNrgmL+qU{FtK>?{lvdZ?!eMm0u4xeBG{>w9=&t4sSn z(?A~jOd96D8skiJ#S!M!^!G`xoDq`Vc;OgU7d+b8&Q7#>qp(`kvb8MY_kdd zj+~%1+p+^|`Of3$Li?=7p&HoDh5dNrFKPekg8i7yJ?&xB#r2-qqR!0MlL>pWO6O6F zx_G@=n(x4wkaoD1{mLdvYfTleQ>;Ygs*(0QtbsI)GDeH`aYJf(t9|@gc1)@c5JStnX!tW9v_XF@f;7F z8F@^lnOQCJnOQPPoQ?M+%?`a|X=XCSd7g=w8ENlV1f=ApEgRxuRYV5+u(_))rhrI&(1ML?&>=$gG@b4XJ%j^16u9lJ2^N}6Ho&jCJ z$j&%UO+G1kf1&!s1FJ1hh|W#KjbNcb9`c7)eebj}y@b-%Ei@=gU)ww;5@mHZs9 zKYuznwdw8WFE5tP{rUy-bzpKo4GwNn-!RN>vABOImzZ)!s(0GC@`HN zCYd-z(GZi2IvU^%u4%XllMFC}4=3SIfj9EuBK$V+2tF)?_W{d+WXz;X*p5)A2=P2F{FCN5=A{v5Jf%g%q#M_ z2&0~(oPI?V@g(>l8pA2A6?G2*%pOo#R!r^i^jk1D)DGActew}0qMfgZB40EFC3L?g zqPX9YMA5E|DAH$hI*-TS!f^uTnCcxw6#bt|6!q2-MY$bBQSUyYsP}E6sP{uonSVRv zvtg}Lzo!w!eXIbbde;&~y~(&`bp)4TBd&yFnlCzYThH+}j$h;WO^%y6KFjgtmO*z& z{9I+9Kh3_dvRVjm@K#9YEpdi(^5Po%vaE`to5&}cB!HD;r=xH~4t)|1vT2<&-c7zD0j_$ud1(*pdRzjpDhI1GW(sTAdq39yyIN$k!sSsXjT7 zFVW9BATRzcp82kdg7Rgsy!Zh2gzZQqnJ-mK?P8m0B`+?# literal 0 HcmV?d00001 diff --git a/features/mbedtls/targets/TARGET_CRYPTOCELL310/binaries/TOOLCHAIN_GCC_ARM/libcc_310_core.a b/features/mbedtls/targets/TARGET_CRYPTOCELL310/binaries/TOOLCHAIN_GCC_ARM/libcc_310_core.a new file mode 100644 index 0000000000000000000000000000000000000000..85abc538277a68621eb4a68b05b11019586368dc GIT binary patch literal 287272 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 Tqg=3@?D0(las+N-B;Ef5M~j&w literal 0 HcmV?d00001 diff --git a/features/mbedtls/targets/TARGET_CRYPTOCELL310/include/ccsw_crys_rsa_shared_types.h b/features/mbedtls/targets/TARGET_CRYPTOCELL310/include/ccsw_crys_rsa_shared_types.h new file mode 100644 index 00000000000..03f561aedf4 --- /dev/null +++ b/features/mbedtls/targets/TARGET_CRYPTOCELL310/include/ccsw_crys_rsa_shared_types.h @@ -0,0 +1,144 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + +#ifndef SW_CRYS_RSA_SHARED_TYPES_H +#define SW_CRYS_RSA_SHARED_TYPES_H + +#ifdef __cplusplus +extern "C" +{ +#endif + + +/** @file + * @brief This file contains the types for the CCSW RSA module. + */ + +/************************ Defines ******************************/ + +/************************************************************************/ +/* the following definitions are only relevant for RSA code on SW */ +/************************************************************************/ +/* Define the maximal allowed width of the exponentiation sliding window +in range 2...6. This define is actual for projects on soft platform. +To minimize code size use the minimum value. To optimize performance +choose the maximum value */ + +/* The valid key size in bits */ +#define SW_CRYS_RSA_MIN_VALID_KEY_SIZE_VALUE_IN_BITS 512 + +#ifndef CRYS_NO_RSA_MAX_KEY_SIZE_4096_BIT_SUPPORT +#define SW_CRYS_RSA_MAX_VALID_KEY_SIZE_VALUE_IN_BITS 4096 +#define SW_CRYS_RSA_MAX_KEY_GENERATION_SIZE_BITS 4096 +#else +#ifndef CRYS_NO_RSA_MAX_KEY_SIZE_3072_BIT_SUPPORT +#define SW_CRYS_RSA_MAX_VALID_KEY_SIZE_VALUE_IN_BITS 3072 +#define SW_CRYS_RSA_MAX_KEY_GENERATION_SIZE_BITS 3072 +#else +#define SW_CRYS_RSA_MAX_VALID_KEY_SIZE_VALUE_IN_BITS 2048 +#define SW_CRYS_RSA_MAX_KEY_GENERATION_SIZE_BITS 2048 +#endif +#endif + + + + + +/* Define the size of the exponentiation temp buffer, used in LLF_PKI exponentiation and NON DEPENDED on + width of the sliding window. The size defined in units equaled to maximal RSA modulus size */ +#define PKI_EXP_CONST_TEMP_BUFF_SIZE_IN_MODULUS_UNITS 7 + +#define PKI_EXP_SLIDING_WINDOW_MAX_VALUE 2 + + /* The maximum buffer size for the 'H' value */ +#define SW_CRYS_RSA_MAXIMUM_MOD_BUFFER_SIZE_IN_WORDS ((SW_CRYS_RSA_MAX_VALID_KEY_SIZE_VALUE_IN_BITS + 64UL ) / 32 ) + + +/* definition of PKI_KEY_GEN_TEMP_BUFF_SIZE_WORDS IS DEPENDED on width of the sliding window*/ +#if( PKI_EXP_SLIDING_WINDOW_MAX_VALUE > 2 ) +#define PKI_KEY_GEN_TEMP_BUFF_SIZE_WORDS \ + ((4 + (1<<(PKI_EXP_SLIDING_WINDOW_MAX_VALUE-2))) * SW_CRYS_RSA_MAXIMUM_MOD_BUFFER_SIZE_IN_WORDS) +#else +#define PKI_KEY_GEN_TEMP_BUFF_SIZE_WORDS \ + (16 * SW_CRYS_RSA_MAXIMUM_MOD_BUFFER_SIZE_IN_WORDS) +#endif + +#ifndef PKI_EXP_WINDOW_TEMP_BUFFER_SIZE_IN_MODULUS_UNITS +#define PKI_EXP_WINDOW_TEMP_BUFFER_SIZE_IN_MODULUS_UNITS (3 + (1 << (PKI_EXP_SLIDING_WINDOW_MAX_VALUE-1))) +#endif + + +/* Define the size of the temp buffer, used in LLF_PKI exponentiation and DEPENDED on + width of the sliding window in words */ +#if (PKI_EXP_CONST_TEMP_BUFF_SIZE_IN_MODULUS_UNITS > PKI_EXP_WINDOW_TEMP_BUFFER_SIZE_IN_MODULUS_UNITS ) +#define PKI_EXP_TEMP_BUFFER_SIZE_IN_WORDS \ + (PKI_EXP_CONST_TEMP_BUFF_SIZE_IN_MODULUS_UNITS * SW_CRYS_RSA_MAXIMUM_MOD_BUFFER_SIZE_IN_WORDS + 2 ) +#else +#define PKI_EXP_TEMP_BUFFER_SIZE_IN_WORDS \ + (PKI_EXP_WINDOW_TEMP_BUFFER_SIZE_IN_MODULUS_UNITS * SW_CRYS_RSA_MAXIMUM_MOD_BUFFER_SIZE_IN_WORDS + 2 ) +#endif + +/* the RSA data type */ +typedef struct SW_Shared_CRYS_RSAPrimeData_t { + /* The aligned input and output data buffers */ + uint32_t DataIn[SW_CRYS_RSA_MAXIMUM_MOD_BUFFER_SIZE_IN_WORDS]; + uint32_t DataOut[SW_CRYS_RSA_MAXIMUM_MOD_BUFFER_SIZE_IN_WORDS]; + + /* #include specific fields that are used by the low level */ + struct { + union { + struct { /* Temporary buffers used for the exponent calculation */ + uint32_t Tempbuff1[PKI_EXP_TEMP_BUFFER_SIZE_IN_WORDS]; + uint32_t Tempbuff2[SW_CRYS_RSA_MAXIMUM_MOD_BUFFER_SIZE_IN_WORDS * 2]; + /* Temporary buffer for self-test support */ + uint32_t TempBuffer[SW_CRYS_RSA_MAXIMUM_MOD_BUFFER_SIZE_IN_WORDS]; + }NonCrt; + + struct { /* Temporary buffers used for the exponent calculation */ + uint32_t Tempbuff1[PKI_EXP_TEMP_BUFFER_SIZE_IN_WORDS]; + uint32_t Tempbuff2[SW_CRYS_RSA_MAXIMUM_MOD_BUFFER_SIZE_IN_WORDS * 2]; + }Crt; + }Data; + }LLF; + +}SW_Shared_CRYS_RSAPrimeData_t; + + + + +#ifdef __cplusplus +} +#endif +#endif diff --git a/features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_aesccm.h b/features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_aesccm.h new file mode 100644 index 00000000000..ccf073208f5 --- /dev/null +++ b/features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_aesccm.h @@ -0,0 +1,315 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + + +#ifndef CRYS_AESCCM_H +#define CRYS_AESCCM_H + +#include "ssi_pal_types.h" +#include "crys_error.h" + +#include "ssi_aes.h" + + +#ifdef __cplusplus +extern "C" +{ +#endif + +/*! +@file +@brief This file contains all of the enums and definitions that are used for the CRYS AESCCM APIs, as well as the APIs themselves. +The API supports AES-CCM and AES-CCM* as defined in ieee-802.15.4. +@defgroup crys_aesccm CryptoCell AES-CCM APIs +@{ +@ingroup cryptocell_api + + +@note +Regarding the AES-CCM*, the API supports only AES-CCM* as defined in ieee-802.15.4-2011; With the instantiations as defined in B.3.2 and the nonce as defined in 7.3.2. +in case of AES-CCM* the flow should be as follows: +
  • AES-CCM* integrated
  • +
    • CRYS_AESCCMStar_NonceGenerate
    • +
    • CRYS_AESCCMStar
+
  • AES-CCM* non-integrated
  • +
    • CRYS_AESCCMStar_NonceGenerate
    • +
    • CRYS_AESCCMStar_Init
    • +
    • CRYS_AESCCM_BlockAdata
    • +
    • CRYS_AESCCM_BlockTextData
    • +
    • CRYS_AESCCM_Finish
+*/ + +/************************ Defines ******************************/ + +/*! AES CCM context size in words.*/ +#define CRYS_AESCCM_USER_CTX_SIZE_IN_WORDS (152/4) + +/*! AES CCM maximal key size in words. */ +#define CRYS_AESCCM_KEY_SIZE_WORDS 8 + +/* nonce and AESCCM-MAC sizes definitions */ +/*! AES CCM NONCE minimal size in bytes. */ +#define CRYS_AESCCM_NONCE_MIN_SIZE_BYTES 7 +/*! AES CCM NONCE maximal size in bytes. */ +#define CRYS_AESCCM_NONCE_MAX_SIZE_BYTES 13 +/*! AES CCM MAC minimal size in bytes..*/ +#define CRYS_AESCCM_MAC_MIN_SIZE_BYTES 4 +/*! AES CCM MAC maximal size in bytes. */ +#define CRYS_AESCCM_MAC_MAX_SIZE_BYTES 16 + +/*! AES CCM star NONCE size in bytes. */ +#define CRYS_AESCCM_STAR_NONCE_SIZE_BYTES 13 +/*! AES CCM star source address size in bytes. */ +#define CRYS_AESCCM_STAR_SOURCE_ADDRESS_SIZE_BYTES 8 + +/*! AES CCM mode - CCM. */ +#define CRYS_AESCCM_MODE_CCM 0 +/*! AES CCM mode - CCM STAR. */ +#define CRYS_AESCCM_MODE_STAR 1 + + +/************************ Typedefs ****************************/ +/*! AES CCM key sizes. */ +typedef enum { + /*! Key size 128 bits. */ + CRYS_AES_Key128BitSize = 0, + /*! Key size 192 bits. */ + CRYS_AES_Key192BitSize = 1, + /*! Key size 256 bits. */ + CRYS_AES_Key256BitSize = 2, + /*! Key size 512 bits. */ + CRYS_AES_Key512BitSize = 3, + /*! Number of optional key sizes. */ + CRYS_AES_KeySizeNumOfOptions, + /*! Reserved. */ + CRYS_AES_KeySizeLast = 0x7FFFFFFF, + +}CRYS_AESCCM_KeySize_t; + +/*! AES_CCM key buffer definition.*/ +typedef uint8_t CRYS_AESCCM_Key_t[CRYS_AESCCM_KEY_SIZE_WORDS * sizeof(uint32_t)]; +/*! AES_CCM MAC buffer definition.*/ +typedef uint8_t CRYS_AESCCM_Mac_Res_t[SASI_AES_BLOCK_SIZE_IN_BYTES]; + +/*! AES_CCM_STAR source address buffer defintion. */ +typedef uint8_t CRYS_AESCCMStar_SourceAddress_t[CRYS_AESCCM_STAR_SOURCE_ADDRESS_SIZE_BYTES]; +/*! AES_CCM_STAR Nonce buffer defintion. */ +typedef uint8_t CRYS_AESCCMStar_Nonce_t[CRYS_AESCCM_STAR_NONCE_SIZE_BYTES]; + +/******************* Context Structure ***********************/ +/*! The user's context structure - the argument type that is passed by the user to the AES CCM APIs */ +typedef struct CRYS_AESCCM_UserContext_t +{ + /*! AES CCM context buffer for internal usage. */ + uint32_t buff[CRYS_AESCCM_USER_CTX_SIZE_IN_WORDS]; +}CRYS_AESCCM_UserContext_t; + + +/************************ Public Functions **********************/ + +/*! +@brief This function initializes the AES CCM context. + +It formats of the input data, calculates AES-MAC value for the formatted B0 block containing control information and +CCM unique value (Nonce), and initializes the AES context structure including the initial CTR0 value. + +@return CRYS_OK on success. +@return A non-zero value on failure as defined crys_aesccm_error.h. +*/ +CRYSError_t CC_AESCCM_Init( + CRYS_AESCCM_UserContext_t *ContextID_ptr, /*!< [in] Pointer to the AES context buffer that is allocated by the user and is used for + the AES operation. */ + SaSiAesEncryptMode_t EncrDecrMode, /*!< [in] Flag specifying whether Encrypt (::SASI_AES_ENCRYPT) or Decrypt + (::SASI_AES_DECRYPT) operation should be performed. */ + CRYS_AESCCM_Key_t CCM_Key, /*!< [in] Pointer to the AES-CCM key. */ + CRYS_AESCCM_KeySize_t KeySizeId, /*!< [in] Enumerator defining the key size (only 128 bit is valid). */ + uint32_t AdataSize, /*!< [in] Full byte length of additional (associated) data. If set to zero, + calling ::CRYS_AESCCM_BlockAdata on the same context would return an error. */ + uint32_t TextSizeQ, /*!< [in] Full length of plain text data. */ + uint8_t *N_ptr, /*!< [in] Pointer to the Nonce. */ + uint8_t SizeOfN, /*!< [in] Nonce byte size. The valid values depend on the ccm mode: +
  • CCM: valid values = [7 .. 13].
  • +
  • CCM*: valid values = [13].
*/ + uint8_t SizeOfT, /*!< [in] AES-CCM MAC (tag) byte size. The valid values depend on the ccm mode: +
  • CCM: valid values = [4, 6, 8, 10, 12, 14, 16].
  • +
  • CCM*: valid values = [0, 4, 8, 16].
*/ + uint32_t ccmMode /*!< [in] Flag specifying whether AES-CCM or AES-CCM* should be performed. */ +); + +/*! Macro defintion for CRYS_AESCCM_Init (AES CCM non-star implementation). */ +#define CRYS_AESCCM_Init(ContextID_ptr, EncrDecrMode, CCM_Key, KeySizeId, AdataSize, TextSizeQ, N_ptr, SizeOfN, SizeOfT) \ + CC_AESCCM_Init(ContextID_ptr, EncrDecrMode, CCM_Key, KeySizeId, AdataSize, TextSizeQ, N_ptr, SizeOfN, SizeOfT, CRYS_AESCCM_MODE_CCM) + +/*! Macro defintion CRYS_AESCCMStar_Init (AES CCM star implementation). */ +#define CRYS_AESCCMStar_Init(ContextID_ptr, EncrDecrMode, CCM_Key, KeySizeId, AdataSize, TextSizeQ, N_ptr, SizeOfN, SizeOfT) \ + CC_AESCCM_Init(ContextID_ptr, EncrDecrMode, CCM_Key, KeySizeId, AdataSize, TextSizeQ, N_ptr, SizeOfN, SizeOfT, CRYS_AESCCM_MODE_STAR) + +/*! +@brief This function receives a CCM context and a block of additional data, and adds it to the AES MAC +calculation. +This API can be called only once per operation context. It should not be called in case AdataSize was set to +zero in ::CC_AESCCM_Init. + +@return CRYS_OK on success. +@return A non-zero value on failure as defined crys_aesccm_error.h. +*/ +CRYSError_t CRYS_AESCCM_BlockAdata( + CRYS_AESCCM_UserContext_t *ContextID_ptr, /*!< [in] Pointer to the context buffer. */ + uint8_t *DataIn_ptr, /*!< [in] Pointer to the additional input data. The buffer must be contiguous. */ + uint32_t DataInSize /*!< [in] Byte size of the additional data. Must match AdataSize parameter provided to + ::CRYS_AESCCM_Init. */ +); + +/*! +@brief This function can be invoked for any block of Text data whose size is a multiple of 16 bytes, +excluding the last block that must be processed by ::CRYS_AESCCM_Finish. +
  • If encrypting: + Continues calculation of the intermediate AES_MAC value of the text data, while simultaneously encrypting the text data using AES_CTR, + starting from CTR value = CTR0+1.
  • +
  • If decrypting: + Continues decryption of the text data, while calculating the intermediate AES_MAC value of decrypted data.
+ +@return CRYS_OK on success. +@return A non-zero value on failure as defined crys_aesccm_error.h. +*/ +CRYSError_t CRYS_AESCCM_BlockTextData( + CRYS_AESCCM_UserContext_t *ContextID_ptr, /*!< [in] Pointer to the context buffer. */ + uint8_t *DataIn_ptr, /*!< [in] Pointer to the additional input data. The buffer must be contiguous. */ + uint32_t DataInSize, /*!< [in] Byte size of the text data block. Must be a multiple of 16 bytes. */ + uint8_t *DataOut_ptr /*!< [out] Pointer to the output data. The size of the output buffer must be at least DataInSize. + The buffer must be contiguous. */ +); + +/*! +@brief This function must be the last to be called on the text data. +It can either be called on the entire text data (if transferred as one block), or on the last block of the text data, +even if total size of text data is equal to 0. +It performs the same operations as ::CRYS_AESCCM_BlockTextData, but additionally: +
  • If encrypting:
  • +
    • If the size of text data is not in multiples of 16 bytes, it pads the remaining bytes with zeros to a full 16-bytes block and + processes the data using AES_MAC and AES_CTR algorithms.
    • +
    • Encrypts the AES_MAC result with AES_CTR using the CTR0 value saved in the context and places the SizeOfT bytes of MAC (tag) + at the end.
+
  • If decrypting:
  • +
    • Processes the text data, except for the last SizeOfT bytes (tag), using AES_CTR and then AES_MAC algorithms.
    • +
    • Encrypts the calculated MAC using AES_CTR based on the saved CTR0 value, and compares it with SizeOfT last bytes of input data (i.e. + tag value).
    • +
    • The function saves the validation result (Valid/Invalid) in the context.
    • +
    • Returns (as the error code) the final CCM-MAC verification result.
+ +@return CRYS_OK on success. +@return A non-zero value on failure as defined crys_aesccm_error.h. +*/ +CEXPORT_C CRYSError_t CRYS_AESCCM_Finish( + CRYS_AESCCM_UserContext_t *ContextID_ptr, /*!< [in] Pointer to the context buffer. */ + uint8_t *DataIn_ptr, /*!< [in] Pointer to the last input data. The buffer must be contiguous. */ + uint32_t DataInSize, /*!< [in] Byte size of the last text data block. Can be zero. */ + uint8_t *DataOut_ptr, /*!< [in] Pointer to the output (cipher or plain text data) data. The buffer must + be contiguous. If DataInSize = 0, output buffer is not required. */ + CRYS_AESCCM_Mac_Res_t MacRes, /*!< [in] MAC result buffer pointer. */ + uint8_t *SizeOfT /*!< [out] AES-CCM MAC byte size as defined in CRYS_AESCCM_Init. */ +); + +/****************************************************************************************************/ +/******** AESCCM FUNCTION ******/ +/****************************************************************************************************/ +/*! +@brief AES CCM combines Counter mode encryption with CBC-MAC authentication. +Input to CCM includes the following elements: +
  • Payload - text data that is both authenticated and encrypted.
  • +
  • Associated data (Adata) - data that is authenticated but not encrypted, e.g., a header.
  • +
  • Nonce - A unique value that is assigned to the payload and the associated data.
+ +@return CRYS_OK on success. +@return A non-zero value on failure as defined crys_aesccm_error.h. +*/ +CIMPORT_C CRYSError_t CC_AESCCM( + SaSiAesEncryptMode_t EncrDecrMode, /*!< [in] A flag specifying whether an AES Encrypt (::SASI_AES_ENCRYPT) or Decrypt + (::SASI_AES_DECRYPT) operation should be performed. */ + CRYS_AESCCM_Key_t CCM_Key, /*!< [in] Pointer to AES-CCM key. */ + CRYS_AESCCM_KeySize_t KeySizeId, /*!< [in] Enumerator defining the key size (only 128 bit is valid). */ + uint8_t *N_ptr, /*!< [in] Pointer to the Nonce. */ + uint8_t SizeOfN, /*!< [in] Nonce byte size. The valid values depend on the ccm mode: +
  • CCM: valid values = [7 .. 13].
  • +
  • CCM*: valid values = [13].
*/ + uint8_t *ADataIn_ptr, /*!< [in] Pointer to the additional input data. The buffer must be contiguous. */ + uint32_t ADataInSize, /*!< [in] Byte size of the additional data. */ + uint8_t *TextDataIn_ptr, /*!< [in] Pointer to the plain-text data for encryption or cipher-text data for decryption. + The buffer must be contiguous. */ + uint32_t TextDataInSize, /*!< [in] Byte size of the full text data. */ + uint8_t *TextDataOut_ptr, /*!< [out] Pointer to the output (cipher or plain text data according to encrypt-decrypt mode) + data. The buffer must be contiguous. */ + uint8_t SizeOfT, /*!< [in] AES-CCM MAC (tag) byte size. The valid values depend on the ccm mode: +
  • CCM: valid values = [4, 6, 8, 10, 12, 14, 16].
  • +
  • CCM*: valid values = [0, 4, 8, 16].
*/ + CRYS_AESCCM_Mac_Res_t Mac_Res, /*!< [in/out] Pointer to the MAC result buffer. */ + uint32_t ccmMode /*!< [in] Flag specifying whether AES-CCM or AES-CCM* should be performed. */ +); + +/*! Macro defintion for CRYS_AESCCM (AES CCM non-star implementation). */ +#define CRYS_AESCCM(EncrDecrMode, CCM_Key, KeySizeId, N_ptr, SizeOfN, ADataIn_ptr, ADataInSize, TextDataIn_ptr, TextDataInSize, TextDataOut_ptr, SizeOfT, Mac_Res) \ + CC_AESCCM(EncrDecrMode, CCM_Key, KeySizeId, N_ptr, SizeOfN, ADataIn_ptr, ADataInSize, TextDataIn_ptr, TextDataInSize, TextDataOut_ptr, SizeOfT, Mac_Res, CRYS_AESCCM_MODE_CCM) + +/*! Macro defintion for CRYS_AESCCMStar (AES CCM star implementation). */ +#define CRYS_AESCCMStar(EncrDecrMode, CCM_Key, KeySizeId, N_ptr, SizeOfN, ADataIn_ptr, ADataInSize, TextDataIn_ptr, TextDataInSize, TextDataOut_ptr, SizeOfT, Mac_Res) \ + CC_AESCCM(EncrDecrMode, CCM_Key, KeySizeId, N_ptr, SizeOfN, ADataIn_ptr, ADataInSize, TextDataIn_ptr, TextDataInSize, TextDataOut_ptr, SizeOfT, Mac_Res, CRYS_AESCCM_MODE_STAR) + + +/*! +@brief This function receives the MAC source address, the frame counter and the MAC size +and returns the required nonce for AES-CCM* as defined in ieee-802.15.4. +This API should be called before CRYS_AESCCMStar and CRYS_AESCCMStar_Init, +and the generated nonce should be provided to these functions. + +@return CRYS_OK on success. +@return A non-zero value on failure as defined crys_aesccm_error.h. +*/ +CRYSError_t CRYS_AESCCMStar_NonceGenerate( + CRYS_AESCCMStar_SourceAddress_t srcAddr, /*!< [in] The MAC address in EUI-64 format. */ + uint32_t FrameCounter, /*!< [in] The MAC frame counter. */ + uint8_t SizeOfT, /*!< [in] AES-CCM* MAC (tag) byte size. Valid values = [0,4,8,16]. */ + CRYS_AESCCMStar_Nonce_t nonce /*!< [out] The required nonce for AES-CCM*. */ +); + +#ifdef __cplusplus +} +#endif + +/** +@} + */ + +#endif /*#ifndef CRYS_AESCCM_H*/ + diff --git a/features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_aesccm_error.h b/features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_aesccm_error.h new file mode 100644 index 00000000000..4ed26e312b9 --- /dev/null +++ b/features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_aesccm_error.h @@ -0,0 +1,134 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + + + +#ifndef CRYS_AESCCM_ERROR_H +#define CRYS_AESCCM_ERROR_H + + +#include "crys_error.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/*! +@file +@brief This module contains the definitions of the CRYS AESCCM errors. +@defgroup crys_aesccm_error CryptoCell AES-CCM specific errors +@{ +@ingroup crys_aesccm +*/ + +/************************ Defines ******************************/ + +/*! CRYS AESCCM module errors. CRYS_AESCCM_MODULE_ERROR_BASE = 0x00F01500. */ +/*! Invalid context pointer. */ +#define CRYS_AESCCM_INVALID_USER_CONTEXT_POINTER_ERROR (CRYS_AESCCM_MODULE_ERROR_BASE + 0x00UL) +/*! Illegal key size. */ +#define CRYS_AESCCM_ILLEGAL_KEY_SIZE_ERROR (CRYS_AESCCM_MODULE_ERROR_BASE + 0x01UL) +/*! Invalid key pointer. */ +#define CRYS_AESCCM_INVALID_KEY_POINTER_ERROR (CRYS_AESCCM_MODULE_ERROR_BASE + 0x02UL) +/*! Invalid encryption mode. */ +#define CRYS_AESCCM_INVALID_ENCRYPT_MODE_ERROR (CRYS_AESCCM_MODULE_ERROR_BASE + 0x03UL) +/*! Context is corrupted. */ +#define CRYS_AESCCM_USER_CONTEXT_CORRUPTED_ERROR (CRYS_AESCCM_MODULE_ERROR_BASE + 0x04UL) +/*! Invalid data in pointer. */ +#define CRYS_AESCCM_DATA_IN_POINTER_INVALID_ERROR (CRYS_AESCCM_MODULE_ERROR_BASE + 0x05UL) +/*! Invalid data out pointer. */ +#define CRYS_AESCCM_DATA_OUT_POINTER_INVALID_ERROR (CRYS_AESCCM_MODULE_ERROR_BASE + 0x06UL) +/*! Illegal data in size. */ +#define CRYS_AESCCM_DATA_IN_SIZE_ILLEGAL (CRYS_AESCCM_MODULE_ERROR_BASE + 0x07UL) +/*! Illegal data in or data out address. */ +#define CRYS_AESCCM_DATA_OUT_DATA_IN_OVERLAP_ERROR (CRYS_AESCCM_MODULE_ERROR_BASE + 0x08UL) +/*! Illegal data out size. */ +#define CRYS_AESCCM_DATA_OUT_SIZE_INVALID_ERROR (CRYS_AESCCM_MODULE_ERROR_BASE + 0x09UL) +/*! Illegal call to process additional data. */ +#define CRYS_AESCCM_ADDITIONAL_BLOCK_NOT_PERMITTED_ERROR (CRYS_AESCCM_MODULE_ERROR_BASE + 0x0AUL) +/*! Illegal dma buffer type. */ +#define CRYS_AESCCM_ILLEGAL_DMA_BUFF_TYPE_ERROR (CRYS_AESCCM_MODULE_ERROR_BASE + 0x0BUL) +/*! Illegal parameter size. */ +#define CRYS_AESCCM_ILLEGAL_PARAMETER_SIZE_ERROR (CRYS_AESCCM_MODULE_ERROR_BASE + 0x0CUL) +/*! Invalid parameter pointer. */ +#define CRYS_AESCCM_ILLEGAL_PARAMETER_PTR_ERROR (CRYS_AESCCM_MODULE_ERROR_BASE + 0x0DUL) +/*! Invalid data type. */ +#define CRYS_AESCCM_ILLEGAL_DATA_TYPE_ERROR (CRYS_AESCCM_MODULE_ERROR_BASE + 0x0EUL) +/*! CCM MAC compare failure. */ +#define CRYS_AESCCM_CCM_MAC_INVALID_ERROR (CRYS_AESCCM_MODULE_ERROR_BASE + 0x0FUL) +/*! Illegal operation. */ +#define CRYS_AESCCM_LAST_BLOCK_NOT_PERMITTED_ERROR (CRYS_AESCCM_MODULE_ERROR_BASE + 0x10UL) +/*! Illegal parameter. */ +#define CRYS_AESCCM_ILLEGAL_PARAMETER_ERROR (CRYS_AESCCM_MODULE_ERROR_BASE + 0x11UL) +/*! Additional data input size is incorrect. */ +#define CRYS_AESCCM_NOT_ALL_ADATA_WAS_PROCESSED_ERROR (CRYS_AESCCM_MODULE_ERROR_BASE + 0x13UL) +/*! Text data input size is incorrect. */ +#define CRYS_AESCCM_NOT_ALL_DATA_WAS_PROCESSED_ERROR (CRYS_AESCCM_MODULE_ERROR_BASE + 0x14UL) +/*! Additional data was already processed (must be processed only once). */ +#define CRYS_AESCCM_ADATA_WAS_PROCESSED_ERROR (CRYS_AESCCM_MODULE_ERROR_BASE + 0x15UL) +/*! Illegal Nonce size. */ +#define CRYS_AESCCM_ILLEGAL_NONCE_SIZE_ERROR (CRYS_AESCCM_MODULE_ERROR_BASE + 0x16UL) +/*! Illegal tag (MAC) size. */ +#define CRYS_AESCCM_ILLEGAL_TAG_SIZE_ERROR (CRYS_AESCCM_MODULE_ERROR_BASE + 0x17UL) + +/*! Illegal context size. */ +#define CRYS_AESCCM_CTX_SIZES_ERROR (CRYS_AESCCM_MODULE_ERROR_BASE + 0x28UL) +/*! Illegal parameters. */ +#define CRYS_AESCCM_ILLEGAL_PARAMS_ERROR (CRYS_AESCCM_MODULE_ERROR_BASE + 0x29UL) +/*! AESCCM is not supported. */ +#define CRYS_AESCCM_IS_NOT_SUPPORTED (CRYS_AESCCM_MODULE_ERROR_BASE + 0xFFUL) + +/************************ Enums ********************************/ + +/************************ Typedefs ****************************/ + +/************************ Structs *****************************/ + +/************************ Public Variables *********************/ + +/************************ Public Functions *********************/ + +#ifdef __cplusplus +} +#endif + +/** +@} + */ + +#endif + + diff --git a/features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_chacha.h b/features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_chacha.h new file mode 100644 index 00000000000..89fb88d2392 --- /dev/null +++ b/features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_chacha.h @@ -0,0 +1,234 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + +/*! +@file +@brief This file contains all of the enums and definitions that are used for the + CRYS CHACHA APIs, as well as the APIs themselves. +@defgroup crys_chacha CryptoCell CHACHA APIs +@{ +@ingroup cryptocell_api +*/ +#ifndef CRYS_CHACHA_H +#define CRYS_CHACHA_H + + +#include "ssi_pal_types.h" +#include "crys_error.h" + + +#ifdef __cplusplus +extern "C" +{ +#endif + +/************************ Defines ******************************/ +/*! CHACHA user's context size in words. */ +#define CRYS_CHACHA_USER_CTX_SIZE_IN_WORDS 17 + +/*! CHACHA block size in words. */ +#define CRYS_CHACHA_BLOCK_SIZE_IN_WORDS 16 +/*! CHACHA block size in bytes. */ +#define CRYS_CHACHA_BLOCK_SIZE_IN_BYTES (CRYS_CHACHA_BLOCK_SIZE_IN_WORDS * sizeof(uint32_t)) + +/*! Nonce buffer max size in words. */ +#define CRYS_CHACHA_NONCE_MAX_SIZE_IN_WORDS 3 +/*! Nonce buffer max size in bytes. */ +#define CRYS_CHACHA_NONCE_MAX_SIZE_IN_BYTES (CRYS_CHACHA_NONCE_MAX_SIZE_IN_WORDS * sizeof(uint32_t)) + +/*! CHACHA KEY maximal size in words. */ +#define CRYS_CHACHA_KEY_MAX_SIZE_IN_WORDS 8 +/*! CHACHA KEY maximal size in bytes. */ +#define CRYS_CHACHA_KEY_MAX_SIZE_IN_BYTES (CRYS_CHACHA_KEY_MAX_SIZE_IN_WORDS * sizeof(uint32_t)) + +/************************ Enums ********************************/ + +/*! Enum defining the CHACHA Encrypt or Decrypt operation mode. */ +typedef enum { + /*! CHACHA encrypt mode. */ + CRYS_CHACHA_Encrypt = 0, + /*! CHACHA decrypt mode. */ + CRYS_CHACHA_Decrypt = 1, + /*! CHACHA maximal number of operations (encrypt/decrypt). */ + CRYS_CHACHA_EncryptNumOfOptions, + + /*! Reserved. */ + CRYS_CHACHA_EncryptModeLast = 0x7FFFFFFF, + +}CRYS_CHACHA_EncryptMode_t; + +/*! Enum defining the CHACHA Nonce size in bits. */ +typedef enum { + /*! 64 bit Nonce size. */ + CRYS_CHACHA_Nonce64BitSize = 0, + /*! 96 bit Nonce size. */ + CRYS_CHACHA_Nonce96BitSize = 1, + /*! CHACHA maximal number of nonce sizes. */ + CRYS_CHACHA_NonceSizeNumOfOptions, + /*! Reserved. */ + CRYS_CHACHA_NonceSizeLast = 0x7FFFFFFF, + +}CRYS_CHACHA_NonceSize_t; + +/************************ Typedefs ****************************/ + +/*! Defines the Nonce buffer 12 bytes array. */ +typedef uint8_t CRYS_CHACHA_Nonce_t[CRYS_CHACHA_NONCE_MAX_SIZE_IN_BYTES]; + +/*! Defines the CHACHA key buffer. */ +typedef uint8_t CRYS_CHACHA_Key_t[CRYS_CHACHA_KEY_MAX_SIZE_IN_BYTES]; + + +/************************ context Structs ******************************/ + +/*! The user's context prototype - the argument type that is passed by the user + to the CHACHA API. The context saves the state of the operation and must be saved by the user + till the end of the APIs flow (for example till ::CRYS_CHACHA_Free is called). */ +typedef struct CRYS_CHACHAUserContext_t { + /* Allocated buffer must be double the size of actual context + * + 1 word for offset management */ + /*! Context buffer for internal use */ + uint32_t buff[CRYS_CHACHA_USER_CTX_SIZE_IN_WORDS]; +}CRYS_CHACHAUserContext_t; + +/************************ Public Variables **********************/ + + +/************************ Public Functions **********************/ + +/****************************************************************************************************/ + +/*! +@brief This function is used to initialize the context for CHACHA operations. + +@return CRYS_OK on success. +@return A non-zero value on failure as defined crys_chacha_error.h. +*/ +CIMPORT_C CRYSError_t CRYS_CHACHA_Init( + CRYS_CHACHAUserContext_t *pContextID, /*!< [in] Pointer to the CHACHA context buffer that is allocated by the user + and is used for the CHACHA operation. */ + CRYS_CHACHA_Nonce_t pNonce, /*!< [in] A buffer containing an nonce. */ + CRYS_CHACHA_NonceSize_t nonceSize, /*!< [in] Enumerator defining the nonce size (only 64 and 96 bit are valid). */ + CRYS_CHACHA_Key_t pKey, /*!< [in] A pointer to the user's key buffer. */ + uint32_t initialCounter, /*!< [in] An initial counter. */ + CRYS_CHACHA_EncryptMode_t EncryptDecryptFlag /*!< [in] A flag specifying whether the CHACHA should perform an Encrypt operation + or a Decrypt operation. */ +); + + +/*! +@brief This function is used to process aligned blocks of CHACHA. +The data in size should be a multiple of chacha block size. + +@return CRYS_OK on success. +@return A non-zero value on failure as defined crys_chacha_error.h. +*/ +CIMPORT_C CRYSError_t CRYS_CHACHA_Block( + CRYS_CHACHAUserContext_t *pContextID, /*!< [in] Pointer to the context buffer. */ + uint8_t *pDataIn, /*!< [in] A pointer to the buffer of the input data to the CHACHA. + The pointer does not need to be aligned. must not be null. */ + uint32_t dataInSize, /*!< [in] The size of the input data. + Must be a multiple of ::CRYS_CHACHA_BLOCK_SIZE_IN_BYTES bytes and must not be 0. */ + uint8_t *pDataOut /*!< [out] A pointer to the buffer of the output data from the CHACHA. + The pointer does not need to be aligned. must not be null. */ +); + + +/*! +@brief This function is used to process the remaining data of CHACHA. +The data in size should be smaller than chacha block size. + +@return CRYS_OK on success. +@return A non-zero value on failure as defined crys_chacha_error.h. +*/ +CIMPORT_C CRYSError_t CRYS_CHACHA_Finish( + CRYS_CHACHAUserContext_t *pContextID, /*!< [in] Pointer to the context buffer. */ + uint8_t *pDataIn, /*!< [in] A pointer to the buffer of the input data to the CHACHA. + The pointer does not need to be aligned. If dataInSize = 0, input buffer is not required. */ + uint32_t dataInSize, /*!< [in] The size of the input data. + zero and non multiple of ::CRYS_CHACHA_BLOCK_SIZE_IN_BYTES are valid. */ + uint8_t *pDataOut /*!< [out] A pointer to the buffer of the output data from the CHACHA. + The pointer does not need to be aligned. If dataInSize = 0, output buffer is not required. */ +); + + +/*! +@brief This function is used to free the context of CHACHA operations. + +@return CRYS_OK on success. +@return A non-zero value on failure as defined crys_chacha_error.h. +*/ +CIMPORT_C CRYSError_t CRYS_CHACHA_Free( + CRYS_CHACHAUserContext_t *pContextID /*!< [in] Pointer to the context buffer. */ +); + + +/*! +@brief This function is used to perform the CHACHA operation in one integrated process. + +@return CRYS_OK on success. +@return A non-zero value on failure as defined crys_chacha_error.h. +*/ +CIMPORT_C CRYSError_t CRYS_CHACHA( + CRYS_CHACHA_Nonce_t pNonce, /*!< [in] A buffer containing an nonce. */ + CRYS_CHACHA_NonceSize_t nonceSize, /*!< [in] Enumerator defining the nonce size (only 64 and 96 bit are valid). */ + CRYS_CHACHA_Key_t pKey, /*!< [in] A pointer to the user's key buffer. */ + uint32_t initialCounter, /*!< [in] An initial counter. */ + CRYS_CHACHA_EncryptMode_t encryptDecryptFlag, /*!< [in] A flag specifying whether the CHACHA should perform an Encrypt operation + or a Decrypt operation. */ + uint8_t *pDataIn, /*!< [in] A pointer to the buffer of the input data to the CHACHA. + The pointer does not need to be aligned. must not be null. */ + uint32_t dataInSize, /*!< [in] The size of the input data. must not be 0. */ + uint8_t *pDataOut /*!< [out] A pointer to the buffer of the output data from the CHACHA. + The pointer does not need to be aligned. must not be null. */ +); + + +/***********************************************************************************/ + +#ifdef __cplusplus +} +#endif + +/** +@} + */ + +#endif /* #ifndef CRYS_CHACHA_H */ + + + + + diff --git a/features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_chacha_error.h b/features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_chacha_error.h new file mode 100644 index 00000000000..93f6141a210 --- /dev/null +++ b/features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_chacha_error.h @@ -0,0 +1,103 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + +#ifndef CRYS_CHACHA_ERROR_H +#define CRYS_CHACHA_ERROR_H + + +#include "crys_error.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/*! +@file +@brief This module contains the definitions of the CRYS CHACHA errors. +@defgroup crys_chacha_error CryptoCell CHACHA specific errors +@{ +@ingroup crys_chacha +*/ + + + +/************************ Defines ******************************/ + +/*! The CRYS CHACHA module errors base address - 0x00F02200. */ +/*! Illegal Nonce. */ +#define CRYS_CHACHA_INVALID_NONCE_ERROR (CRYS_CHACHA_MODULE_ERROR_BASE + 0x01UL) +/*! Illegal key size. */ +#define CRYS_CHACHA_ILLEGAL_KEY_SIZE_ERROR (CRYS_CHACHA_MODULE_ERROR_BASE + 0x02UL) +/*! Illegal key pointer. */ +#define CRYS_CHACHA_INVALID_KEY_POINTER_ERROR (CRYS_CHACHA_MODULE_ERROR_BASE + 0x03UL) +/*! Illegal operation mode. */ +#define CRYS_CHACHA_INVALID_ENCRYPT_MODE_ERROR (CRYS_CHACHA_MODULE_ERROR_BASE + 0x04UL) +/*! Illegal data in pointer. */ +#define CRYS_CHACHA_DATA_IN_POINTER_INVALID_ERROR (CRYS_CHACHA_MODULE_ERROR_BASE + 0x05UL) +/*! Illegal data out pointer. */ +#define CRYS_CHACHA_DATA_OUT_POINTER_INVALID_ERROR (CRYS_CHACHA_MODULE_ERROR_BASE + 0x06UL) +/*! Illegal user context. */ +#define CRYS_CHACHA_INVALID_USER_CONTEXT_POINTER_ERROR (CRYS_CHACHA_MODULE_ERROR_BASE + 0x07UL) +/*! Illegal user context size. */ +#define CRYS_CHACHA_CTX_SIZES_ERROR (CRYS_CHACHA_MODULE_ERROR_BASE + 0x08UL) +/*! Illegal Nonce pointer. */ +#define CRYS_CHACHA_INVALID_NONCE_PTR_ERROR (CRYS_CHACHA_MODULE_ERROR_BASE + 0x09UL) +/*! Illegal data in size. */ +#define CRYS_CHACHA_DATA_IN_SIZE_ILLEGAL (CRYS_CHACHA_MODULE_ERROR_BASE + 0x0AUL) +/*! General error. */ +#define CRYS_CHACHA_GENERAL_ERROR (CRYS_CHACHA_MODULE_ERROR_BASE + 0x0BUL) +/*! CHACHA is not supported. */ +#define CRYS_CHACHA_IS_NOT_SUPPORTED (CRYS_CHACHA_MODULE_ERROR_BASE + 0xFFUL) + +/************************ Enums ********************************/ + +/************************ Typedefs ****************************/ + +/************************ Structs *****************************/ + +/************************ Public Variables *********************/ + +/************************ Public Functions *********************/ + +#ifdef __cplusplus +} +#endif +/** +@} + */ +#endif + + diff --git a/features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_chacha_poly.h b/features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_chacha_poly.h new file mode 100644 index 00000000000..f9a7ce15fa8 --- /dev/null +++ b/features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_chacha_poly.h @@ -0,0 +1,95 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + +/*! +@file +@brief This file contains all of the enums and definitions that are used for the + CRYS CHACHA-POLY APIs, as well as the APIs themselves. +@defgroup crys_chacha_poly CryptoCell CHACHA-POLY APIs +@{ +@ingroup cryptocell_api +*/ +#ifndef CRYS_CHACHA_POLY_H +#define CRYS_CHACHA_POLY_H + + +#include "ssi_pal_types.h" +#include "crys_error.h" +#include "crys_chacha.h" +#include "crys_poly.h" + + +#ifdef __cplusplus +extern "C" +{ +#endif + + +/*! +@brief This function is used to perform the CHACHA-POLY encryption and authentication operation. + +@return CRYS_OK on success. +@return A non-zero value on failure as defined crys_chacha_poly_error.h. +*/ +CIMPORT_C CRYSError_t CRYS_CHACHA_POLY( + CRYS_CHACHA_Nonce_t pNonce, /*!< [in] A pointer to a buffer containing the nonce value. */ + CRYS_CHACHA_Key_t pKey, /*!< [in] A pointer to the user's key buffer. */ + CRYS_CHACHA_EncryptMode_t encryptDecryptFlag, /*!< [in] A flag specifying whether the CHACHA-POLY should perform an Encrypt or + Decrypt operation. */ + uint8_t *pAddData, /*!< [in] A pointer to the buffer of the additional data to the POLY. + The pointer does not need to be aligned. must not be null. */ + size_t addDataSize, /*!< [in] The size of the input data. must not be 0. */ + uint8_t *pDataIn, /*!< [in] A pointer to the buffer of the input data to the CHACHA. + The pointer does not need to be aligned. must not be null. */ + size_t dataInSize, /*!< [in] The size of the input data. must not be 0. */ + uint8_t *pDataOut, /*!< [out] A pointer to the buffer of the output data from the CHACHA. + must not be null. */ + CRYS_POLY_Mac_t macRes /*!< [in/out] Pointer to the MAC result buffer.*/ +); + + + +#ifdef __cplusplus +} +#endif +/** +@} + */ +#endif /* #ifndef CRYS_CHACHA_POLY_H */ + + + + + diff --git a/features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_chacha_poly_error.h b/features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_chacha_poly_error.h new file mode 100644 index 00000000000..f5465ecfacf --- /dev/null +++ b/features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_chacha_poly_error.h @@ -0,0 +1,95 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + +#ifndef CRYS_CHACHA_POLY_ERROR_H +#define CRYS_CHACHA_POLY_ERROR_H + + +#include "crys_error.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/*! +@file +@brief This module contains the definitions of the CRYS CHACHA POLY errors. +@defgroup crys_chacha_poly_error CryptoCell CHACHA POLY specific errors +@{ +@ingroup crys_chacha_poly +*/ + + + +/************************ Defines ******************************/ + +/*! The CRYS CHACHA POLY module errors base address - 0x00F02400. */ +/*! Invalid Additional data. */ +#define CRYS_CHACHA_POLY_ADATA_INVALID_ERROR (CRYS_CHACHA_POLY_MODULE_ERROR_BASE + 0x01UL) +/*! Invalid input data. */ +#define CRYS_CHACHA_POLY_DATA_INVALID_ERROR (CRYS_CHACHA_POLY_MODULE_ERROR_BASE + 0x02UL) +/*! Illegal encryption mode. */ +#define CRYS_CHACHA_POLY_ENC_MODE_INVALID_ERROR (CRYS_CHACHA_POLY_MODULE_ERROR_BASE + 0x03UL) +/*! Illegal data size. */ +#define CRYS_CHACHA_POLY_DATA_SIZE_INVALID_ERROR (CRYS_CHACHA_POLY_MODULE_ERROR_BASE + 0x04UL) +/*! Key generation error. */ +#define CRYS_CHACHA_POLY_GEN_KEY_ERROR (CRYS_CHACHA_POLY_MODULE_ERROR_BASE + 0x05UL) +/*! CHACHA Key generation error. */ +#define CRYS_CHACHA_POLY_ENCRYPTION_ERROR (CRYS_CHACHA_POLY_MODULE_ERROR_BASE + 0x06UL) +/*! Authentication error. */ +#define CRYS_CHACHA_POLY_AUTH_ERROR (CRYS_CHACHA_POLY_MODULE_ERROR_BASE + 0x07UL) +/*! MAC comparison error. */ +#define CRYS_CHACHA_POLY_MAC_ERROR (CRYS_CHACHA_POLY_MODULE_ERROR_BASE + 0x08UL) + +/************************ Enums ********************************/ + +/************************ Typedefs ****************************/ + +/************************ Structs *****************************/ + +/************************ Public Variables *********************/ + +/************************ Public Functions *********************/ + +#ifdef __cplusplus +} +#endif +/** +@} + */ +#endif + + diff --git a/features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_dh.h b/features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_dh.h new file mode 100644 index 00000000000..be0deb907cd --- /dev/null +++ b/features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_dh.h @@ -0,0 +1,446 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + + + +#ifndef _CRYS_DH_H +#define _CRYS_DH_H + +#include "crys_rsa_types.h" +#include "crys_kdf.h" +#include "crys_rnd.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + + +/*! +@file +@brief This module defines the API that supports Diffie-Hellman key exchange, as defined in [PKCS3] and in [X9.42] (key lengths 1024 and 2048 bits). +@defgroup crys_dh CryptoCell DH APIs +@{ +@ingroup cryptocell_api +*/ + + +/************************ Defines ******************************/ +/*! Defintion for DH public key.*/ +#define CRYS_DHPubKey_t CRYSRSAPubKey_t + +/*! Maximal valid key size in bits.*/ +#define CRYS_DH_MAX_VALID_KEY_SIZE_VALUE_IN_BITS CRYS_RSA_MAX_VALID_KEY_SIZE_VALUE_IN_BITS /*!< \internal RL restrict to 2048 */ +/*! Minimal valid key size in bits.*/ +#define CRYS_DH_MIN_VALID_KEY_SIZE_VALUE_IN_BITS 1024 /*!< Size limitation according to ANSI standard */ +/*! Maximal modulus size in bytes.*/ +#define CRYS_DH_MAX_MOD_SIZE_IN_BYTES (CRYS_DH_MAX_VALID_KEY_SIZE_VALUE_IN_BITS / SASI_BITS_IN_BYTE) +/*! Maximal modulus size in words.*/ +#define CRYS_DH_MAX_MOD_SIZE_IN_WORDS (CRYS_DH_MAX_MOD_SIZE_IN_BYTES/sizeof(uint32_t)) + +/*! Modulus buffer size in words.*/ +#define CRYS_DH_MAX_MOD_BUFFER_SIZE_IN_WORDS (CRYS_DH_MAX_MOD_SIZE_IN_WORDS + 2) +/*! Maximal domain generation size in bits.*/ +#define CRYS_DH_DOMAIN_GENERATION_MAX_SIZE_BITS CRYS_RSA_MAX_KEY_GENERATION_SIZE_BITS /*!< \internal RL restrict to 2048 */ + +/*! Defintion for DH primitives data.*/ +#define CRYS_DHPrimeData_t CRYS_RSAPrimeData_t +/*! Defintion for DH public key.*/ +#define CRYS_DHUserPubKey_t CRYS_RSAUserPubKey_t +/*! Defintion for DH other info.*/ +#define CRYS_DH_OtherInfo_t CRYS_KDF_OtherInfo_t + +/*! Keying data size is in bytes*/ +#define CRYS_DH_MAX_SIZE_OF_KEYING_DATA CRYS_KDF_MAX_SIZE_OF_KEYING_DATA + +/************************ Enums ********************************/ + +/*! DH operations mode */ +typedef enum +{ + /*! PKCS3 operation mode. */ + CRYS_DH_PKCS3_mode = 0, + /*! ANSI X942 operation mode. */ + CRYS_DH_ANSI_X942_mode = 1, + /*! Total number of operation modes. */ + CRYS_DH_NumOfModes, + + /*! Reserved. */ + CRYS_DH_OpModeLast = 0x7FFFFFFF, + +}CRYS_DH_OpMode_t; + +/*! HASH operation modes */ +typedef enum +{ + /*! SHA1 operation mode. */ + CRYS_DH_HASH_SHA1_mode = CRYS_HASH_SHA1_mode, + /*! SHA224 operation mode. */ + CRYS_DH_HASH_SHA224_mode = CRYS_HASH_SHA224_mode, + /*! SHA256 operation mode. */ + CRYS_DH_HASH_SHA256_mode = CRYS_HASH_SHA256_mode, + /*! SHA384 operation mode. */ + CRYS_DH_HASH_SHA384_mode = CRYS_HASH_SHA384_mode, + /*! SHA512 operation mode. */ + CRYS_DH_HASH_SHA512_mode = CRYS_HASH_SHA512_mode, + /*! MD5 operation mode (not used in DH). */ + CRYS_DH_HASH_MD5_mode = CRYS_HASH_MD5_mode, /*!< \internal not used in DH */ + /*! Total number of HASH modes. */ + CRYS_DH_HASH_NumOfModes = CRYS_HASH_MD5_mode, + /*! Reserved. */ + CRYS_DH_HASH_OperationModeLast = 0x7FFFFFFF, + +}CRYS_DH_HASH_OpMode_t; + +/*! Key derivation modes. */ +typedef enum +{ + /*! ASN1 derivation mode.*/ + CRYS_DH_ASN1_Der_mode = CRYS_KDF_ASN1_DerivMode, + /*! Concatination derivation mode.*/ + CRYS_DH_Concat_Der_mode = CRYS_KDF_ConcatDerivMode, + /*! X963 derivation mode.*/ + CRYS_DH_X963_DerMode = CRYS_KDF_ConcatDerivMode, + /*! Reserved. */ + CRYS_DH_DerivationFunc_ModeLast= 0x7FFFFFFF, + +}CRYS_DH_DerivationFunc_Mode; + + +/************************ Typedefs *************************************/ +/*! Temporary buffer structure for internal usage.*/ +typedef struct +{ + /*! Temporary primitives data */ + CRYS_DHPrimeData_t PrimeData; + /*! Public key. */ + CRYS_DHPubKey_t PubKey; + /*! Temporary buffer for internal usage. */ + uint32_t TempBuff[CRYS_DH_MAX_MOD_BUFFER_SIZE_IN_WORDS]; +} CRYS_DH_ExpTemp_t; + +/*! Temporary buffer structure for internal usage. */ +typedef struct +{ + /*! Temporary primitives data */ + CRYS_DHPrimeData_t PrimeData; + /*! User's public key. */ + CRYS_DHUserPubKey_t UserPubKey; + /*! Temporary buffer for internal usage. */ + uint32_t TempBuff[CRYS_DH_MAX_MOD_BUFFER_SIZE_IN_WORDS]; +} CRYS_DH_Temp_t; + +/*! Temporary buffer structure for internal usage. */ +typedef struct +{ + /*! Temporary primitives data */ + CRYS_DHPrimeData_t PrimeData; + /*! User's public key. */ + CRYS_DHUserPubKey_t UserPubKey; + /*! Temporary buffer for internal usage. */ + uint32_t TempBuff[2*CRYS_DH_MAX_MOD_BUFFER_SIZE_IN_WORDS]; +} CRYS_DH_HybrTemp_t; + +/*! Defintion of buffer used for FIPS Known Answer Tests. */ +typedef struct +{ + /*! Public key. */ + CRYS_DHUserPubKey_t pubKey; + /*! Temporary primitives data */ + CRYS_DHPrimeData_t primeData; + /*! Buffer for the secret value.*/ + uint8_t secretBuff[CRYS_DH_MIN_VALID_KEY_SIZE_VALUE_IN_BITS/SASI_BITS_IN_BYTE]; // KAT tests uses 1024 bit key +} CRYS_DH_FipsKat_t; + + +/************************ Structs **************************************/ + +/************************ Public Variables ******************************/ + +/************************ Public Functions ******************************/ + +/*******************************************************************************************/ + +/*! +@brief This function has two purposes: +
  1. Randomly generate the client private key according to the choosen version [PKCS3] or [ANSI X9.42].
  2. +
  3. Computes the client public key as follows: ClientPub = Generator^Prv mod Prime, where '^' is the symbol of exponentiation.
+This function should not be called directly. Instead, use the macros ::CRYS_DH_PKCS3_GeneratePubPrv and ::CRYS_DH_ANSI_X942_GeneratePubPrv. +\note +All buffer parameters should be in Big-Endian form. + +@return CRYS_OK on success. +@return A non-zero value on failure as defined crys_dh_error.h, crys_rnd_error.h or crys_rsa_error.h. + */ +CIMPORT_C CRYSError_t _DX_DH_GeneratePubPrv( + void *rndState_ptr, /*!< [in/out] Pointer to the RND state structure. */ + SaSiRndGenerateVectWorkFunc_t rndGenerateVectFunc, /*!< [in] Pointer to the random vector generation function. */ + uint8_t *Generator_ptr, /*!< [in] Pointer to the Generator octet string. */ + uint16_t GeneratorSize, /*!< [in] The size of the Generator string (in bytes). */ + uint8_t *Prime_ptr, /*!< [in] Pointer to the Prime octet string P (used as modulus in the algorithm). */ + uint16_t PrimeSize, /*!< [in] The size of the Prime string in bytes. */ + uint16_t L, /*!< [in] Exact size in bits of the Prime to be generated (relevant only for [PKCS3]): +
  • If L!=0, force the private key to be [2^(L-1) ? Prv < 2^L], where '^' + indicates exponentiation.
  • +
  • If L = 0 then [0 < Prv < P-1].
*/ + uint8_t *Q_ptr, /*!< [in] Relevant only for [ANSI X9.42] - Pointer to the Q octet string in the range: + 1 <= Prv <= Q-1 or 1 < Prv < Q-1. */ + uint16_t QSize, /*!< [in] Relevant only for [ANSI X9.42] - Size of the Q string (in bytes). */ + CRYS_DH_OpMode_t DH_mode, /*!< [in] An enumerator declaring whether this is [PKCS3] or [ANSI X9.42] mode. */ + CRYS_DHUserPubKey_t *tmpPubKey_ptr, /*!< [in] Pointer to a temporary buffer for public key structure. Used for the + exponentiation function. */ + CRYS_DHPrimeData_t *tmpPrimeData_ptr, /*!< [in] Pointer to a structure holding internal temporary buffers. */ + uint8_t *ClientPrvKey_ptr, /*!< [out] Pointer to the Private key Prv. This buffer should be at least the following + size (in bytes): +
  • If L is provided: (L+7)/8.
  • +
  • If L is NULL: \p PrimeSize.
*/ + uint16_t *ClientPrvKeySize_ptr, /*!< [in/out] Pointer to the Private key size: +
  • Input - size of the given buffer.
  • +
  • Output - actual size of the generated private key.
*/ + uint8_t *ClientPub1_ptr, /*!< [out] Pointer to the Public key. This buffer should be at least \p PrimeSize bytes. */ + uint16_t *ClientPubSize_ptr /*!< [in/out] Pointer to the Public key size: +
  • Input - size of the given buffer.
  • +
  • Output - actual size of the generated public key.
*/ +); + + +/* macro for calling the GeneratePubPrv function on PKCS#3 mode: Q is irrelevant */ +/*--------------------------------------------------------------------------------*/ +/*! +This macro is used to generate the public and private DH keys according to [PKCS3]. For a description of the parameters see ::_DX_DH_GeneratePubPrv. +*/ +#define CRYS_DH_PKCS3_GeneratePubPrv(rndState_ptr, rndGenerateVectFunc, Generator_ptr,GeneratorSize,\ + Prime_ptr,PrimeSize,\ + L,\ + tmpPubKey_ptr,tmpPrimeData_ptr,\ + ClientPrvKey_ptr,ClientPrvKeySize_ptr,\ + ClientPub_ptr,ClientPubSize_ptr)\ + _DX_DH_GeneratePubPrv(rndState_ptr, rndGenerateVectFunc, (Generator_ptr),(GeneratorSize),\ + (Prime_ptr),(PrimeSize),\ + (L),\ + (uint8_t *)NULL,(uint16_t)0,\ + CRYS_DH_PKCS3_mode,\ + (tmpPubKey_ptr),(tmpPrimeData_ptr),\ + (ClientPrvKey_ptr),(ClientPrvKeySize_ptr),\ + (ClientPub_ptr),(ClientPubSize_ptr)) + +/*! +This macro is used to generate the public and private DH keys according to [ANSI X9.42]. For a description of the parameters see ::_DX_DH_GeneratePubPrv. +*/ +#define CRYS_DH_ANSI_X942_GeneratePubPrv(rndState_ptr, rndGenerateVectFunc, Generator_ptr,GeneratorSize,Prime_ptr,PrimeSize,\ + Q_ptr,QSize,\ + tmpPubKey_ptr,tmpPrimeData_ptr,\ + ClientPrvKey_ptr,ClientPrvKeySize_ptr,\ + ClientPub_ptr,ClientPubSize_ptr)\ + _DX_DH_GeneratePubPrv(rndState_ptr, rndGenerateVectFunc, (Generator_ptr),(GeneratorSize),\ + (Prime_ptr),(PrimeSize),\ + (uint16_t)0,\ + (Q_ptr),(QSize),\ + CRYS_DH_ANSI_X942_mode,\ + (tmpPubKey_ptr),(tmpPrimeData_ptr),\ + (ClientPrvKey_ptr),(ClientPrvKeySize_ptr),\ + (ClientPub_ptr),(ClientPubSize_ptr)) + + +/*******************************************************************************************/ +/*! +@brief This function computes the shared secret key (value) accordng to [ANSI X9.42], 7.5.1: + SecretKey = ServerPubKey ^ ClientPrvKey mod Prime. +\note
  • All buffer parameters should be in Big-Endian form.
  • +
  • The user must obtain assurance of validity of the public key, using one of methods, +described in [ANSI X9.42] paragraph 7.4.
  • +
  • The actual size of the private key (in bits) must be not less than 2 and not greater than the actual +size of the Prime (modulus in bits).
+ +@return CRYS_OK on success. +@return A non-zero value on failure as defined in crys_dh_error.h or crys_rsa_error.h. +*/ +CIMPORT_C CRYSError_t CRYS_DH_GetSecretKey( + uint8_t *ClientPrvKey_ptr, /*!< [in] Pointer to the Private key octet string Prv < Prime. */ + uint16_t ClientPrvKeySize, /*!< [in] The Private key Size (in bytes). */ + uint8_t *ServerPubKey_ptr, /*!< [in] Pointer to the Server public key octet string. */ + uint16_t ServerPubKeySize, /*!< [in] The Server Public key Size (in bytes). */ + uint8_t *Prime_ptr, /*!< [in] Pointer to the Prime octet string. */ + uint16_t PrimeSize, /*!< [in] The size of the Prime string. */ + CRYS_DHUserPubKey_t *tmpPubKey_ptr, /*!< [in] Pointer to the public key structure. Used for the exponentiation + operation function. Need not be initialized. */ + CRYS_DHPrimeData_t *tmpPrimeData_ptr, /*!< [in] Pointer to a structure containing internal temp buffers. */ + uint8_t *SecretKey_ptr, /*!< [out] Pointer to the secret key octet string. This buffer should be at + least PrimeSize bytes. */ + uint16_t *SecretKeySize_ptr /*!< [in/out] Pointer to the secret key Buffer Size. This buffer should be at + least of PrimeSize bytes: +
  • Input - size of the given buffer.
  • +
  • Output - actual size.
*/ +); + + +/******************************************************************************************/ +/*! +@brief This function extracts the shared secret keying data from the shared secret value. It should be called by using +macros ::CRYS_DH_X942_GetSecretDataAsn1 and ::CRYS_DH_X942_GetSecretDataConcat. + +\note +
  • The "other info" argument and its AlgorithmID entry are mandatory only for ASN1 key derivation, and optional for +the other derivation modes.
  • +
  • If used, all entries of the structure should be initialized with relevant data and size, prior to calling this function +(entry size of empty fields must be set to 0).
  • +
  • All buffers arguments are represented in Big-Endian form.
+ +@return CRYS_OK on success. +@return A non-zero value on failure as defined in crys_dh_error.h, crys_rsa_error.h, crys_kdf_error.h or crys_hash_error.h. +*/ + CIMPORT_C CRYSError_t CRYS_DH_X942_GetSecretData( + uint8_t *ClientPrvKey_ptr, /*!< [in] Pointer to the Private key octet string. */ + uint16_t ClientPrvKeySize, /*!< [in] The Private key size (in bytes). */ + uint8_t *ServerPubKey_ptr, /*!< [in] Pointer to the Server public key octet string. */ + uint16_t ServerPubKeySize, /*!< [in] The Server Public key size (in bytes). */ + uint8_t *Prime_ptr, /*!< [in] Pointer to the Prime octet string. */ + uint16_t PrimeSize, /*!< [in] The size of the Prime string. */ + CRYS_DH_OtherInfo_t *otherInfo_ptr, /*!< [in] Pointer to structure containing other data, shared by two entities + sharing the secret keying data. + The Maximal size of each data entry of "other info" is limited - see crys_kdf.h + for the defined value. */ + CRYS_DH_HASH_OpMode_t hashMode, /*!< [in] One of the supported SHA-x HASH modes. The supported modes are according to the supported + HASH modes for the product (and MD5 is not supported). */ + CRYS_DH_DerivationFunc_Mode DerivFunc_mode, /*!< [in] The enumerator ID of key derivation function mode. ASN1 or Concatenation + modes are supported. */ + CRYS_DH_Temp_t *tmpBuff_ptr, /*!< [in] A pointer to the DH temp buffer structure. Not initialized. */ + uint8_t *SecretKeyingData_ptr, /*!< [out] Pointer to the secret key octet string. This buffer should be at least + PrimeSize bytes. */ + uint16_t SecretKeyingDataSize /*!< [in] The required Secret Keying data size (in bytes). Must be larger than 0, + and smaller than the maximal - CRYS_DH_MAX_SIZE_OF_KEYING_DATA. */ +); + +/****************************************************************/ +/*! +This macro implements the DH [ANSI X9.42] standard. It derives a secret key using the Derivation function based on ASN.1. For a +description of the parameters see ::CRYS_DH_X942_GetSecretData.*/ +#define CRYS_DH_X942_GetSecretDataAsn1(ClientPrvKey_ptr,ClientPrvKeySize,ServerPubKey_ptr,ServerPubKeySize,Prime_ptr,PrimeSize,otherInfo_ptr,hashMode,tmpBuff_ptr,SecretKeyingData_ptr,SecretKeyingDataSize)\ + CRYS_DH_X942_GetSecretData((ClientPrvKey_ptr),(ClientPrvKeySize),(ServerPubKey_ptr),(ServerPubKeySize),(Prime_ptr),(PrimeSize),(otherInfo_ptr),(hashMode),(CRYS_DH_ASN1_Der_mode),(tmpBuff_ptr),(SecretKeyingData_ptr),(SecretKeyingDataSize)) +/*! +This macro implements the DH [ANSI X9.42] standard. It derives a secret key using the Derivation function based on concatenation of HASHed data. +For a description of the parameters see ::CRYS_DH_X942_GetSecretData.*/ +#define CRYS_DH_X942_GetSecretDataConcat(ClientPrvKey_ptr,ClientPrvKeySize,ServerPubKey_ptr,ServerPubKeySize,Prime_ptr,PrimeSize,otherInfo_ptr,hashMode,tmpBuff_ptr,SecretKeyingData_ptr,SecretKeyingDataSize)\ + CRYS_DH_X942_GetSecretData((ClientPrvKey_ptr),(ClientPrvKeySize),(ServerPubKey_ptr),(ServerPubKeySize),(Prime_ptr),(PrimeSize),(otherInfo_ptr),(hashMode),(CRYS_DH_Concat_Der_mode),(tmpBuff_ptr),(SecretKeyingData_ptr),(SecretKeyingDataSize)) + + +/****************************************************************/ +/*! +@brief The function computes shared secret data using two pairs of public and private keys: + +
  • SecretKey1 = ServerPubKey1^ClientPrvKey1 mod Prime.
  • +
  • SecretKey2 = ServerPubKey2^ClientPrvKey2 mod Prime.
+It uses the Derivation function to derive secret keying data from the two secret keys (values). +This function may be called directly, or by using macros ::CRYS_DH_X942_HybridGetSecretDataAsn1 and ::CRYS_DH_X942_HybridGetSecretDataConcat +described above. + +\note +
  • The "other info" argument and its AlgorithmID entry are mandatory only for ASN1 key derivation, and optional for the other derivation modes.
  • +If used, all entries of the structure should be initialized with relevant data and size, prior to calling this function +(entry size of empty fields must be set to 0). +
  • All buffers arguments are represented in Big-Endian form.
+ +@return CRYS_OK on success. +@return A non-zero value on failure as defined in crys_dh_error.h, crys_rsa_error.h or crys_hash_error.h. +*/ +CIMPORT_C CRYSError_t CRYS_DH_X942_HybridGetSecretData( + uint8_t *ClientPrvKey_ptr1, /*!< [in] Pointer to the First Private key octet string number. */ + uint16_t ClientPrvKeySize1, /*!< [in] The First Private key Size (in bytes). */ + uint8_t *ClientPrvKey_ptr2, /*!< [in] Pointer to the Second Private key octet string. */ + uint16_t ClientPrvKeySize2, /*!< [in] The Second Private key Size (in bytes). */ + uint8_t *ServerPubKey_ptr1, /*!< [in] Pointer to the First Server public key octet string. */ + uint16_t ServerPubKeySize1, /*!< [in] The First Server Public key Size (in bytes). */ + uint8_t *ServerPubKey_ptr2, /*!< [in] Pointer to the Second Server public key octet string. */ + uint16_t ServerPubKeySize2, /*!< [in] The Second Server Public key Size (in bytes). */ + uint8_t *Prime_ptr, /*!< [in] Pointer to the Prime octet string. */ + uint16_t PrimeSize, /*!< [in] The size of the Prime string. */ + CRYS_DH_OtherInfo_t *otherInfo_ptr, /*!< [in] Pointer to structure containing optional other data, shared by two entities + sharing the secret keying data. */ + CRYS_DH_HASH_OpMode_t hashMode, /*!< [in] One of the supported SHA-x HASH modes. The supported modes are according to the supported + HASH modes for the product (and MD5 is not supported). */ + CRYS_DH_DerivationFunc_Mode DerivFunc_mode, /*!< [in] The type of function to use to derive the secret key to the key data. + ASN.1 or Concatenation modes are supported. */ + CRYS_DH_HybrTemp_t *tmpDhHybr_ptr, /*!< [in] Pointer to a CRYS_DH_Temp_t structure that contains temp buffers for + internal operations. */ + uint8_t *SecretKeyingData_ptr, /*!< [out] Pointer to the secret key octet string. This buffer should be at least + of size PrimeSize bytes. */ + uint16_t SecretKeyingDataSize /*!< [in] The required Secret Keying data size (in bytes). Must be larger than 0, + and smaller than CRYS_DH_MAX_SIZE_OF_KEYING_DATA. */ +); + + +/****************************************************************/ +/*! +This macro implements the DH [X9.42] standard deriving a hybrid secret key from two public-private pair of keys using the Derivation function based on ASN.1. +For a description of the parameters see ::CRYS_DH_X942_HybridGetSecretData.*/ +#define CRYS_DH_X942_HybridGetSecretDataAsn1(ClientPrvKey_ptr1,ClientPrvKeySize1,ClientPrvKey_ptr2,ClientPrvKeySize2,ServerPubKey_ptr1,ServerPubKeySize1,ServerPubKey_ptr2,ServerPubKeySize2,Prime_ptr,PrimeSize,otherInfo_ptr,hashFunc,tmpDhHybr_ptr,SecretKeyingData_ptr,SecretKeyingDataSize)\ + CRYS_DH_X942_HybridGetSecretData((ClientPrvKey_ptr1),(ClientPrvKeySize1),(ClientPrvKey_ptr2),(ClientPrvKeySize2),(ServerPubKey_ptr1),(ServerPubKeySize1),(ServerPubKey_ptr2),(ServerPubKeySize2),(Prime_ptr),(PrimeSize),(otherInfo_ptr),(hashFunc),CRYS_DH_ASN1_Der_mode,(tmpDhHybr_ptr),(SecretKeyingData_ptr),(SecretKeyingDataSize)) + +/*! +This macro implements the DH [X9.42] standard, deriving a hybrid secret key from two pairs of public-private keys, using the Derivation +function based on concatenation using SHA-x HASH. For a description of the parameters see ::CRYS_DH_X942_HybridGetSecretData. +*/ +#define CRYS_DH_X942_HybridGetSecretDataConcat(ClientPrvKey_ptr1,ClientPrvKeySize1,ClientPrvKey_ptr2,ClientPrvKeySize2,ServerPubKey_ptr1,ServerPubKeySize1,ServerPubKey_ptr2,ServerPubKeySize2,Prime_ptr,PrimeSize,otherInfo_ptr,hashFunc,tmpDhHybr_ptr,SecretKeyingData_ptr,SecretKeyingDataSize)\ + CRYS_DH_X942_HybridGetSecretData((ClientPrvKey_ptr1),(ClientPrvKeySize1),(ClientPrvKey_ptr2),(ClientPrvKeySize2),(ServerPubKey_ptr1),(ServerPubKeySize1),(ServerPubKey_ptr2),(ServerPubKeySize2),(Prime_ptr),(PrimeSize),(otherInfo_ptr),(hashFunc),CRYS_DH_Concat_Der_mode,(tmpDhHybr_ptr),(SecretKeyingData_ptr),(SecretKeyingDataSize)) + + +/******************************************************************************************/ +/*! +@brief The function checks the obtained DH public key according to its domain parameters [ANSI X9.42-2001] + +\note +Assuming: The DH domain parameters are valid. + +@return CRYS_OK on success. +@return A non-zero value on failure as defined in crys_dh_error.h. +*/ +CIMPORT_C CRYSError_t CRYS_DH_CheckPubKey( + uint8_t *modP_ptr, /*!< [in] The pointer to the modulus (prime) P. */ + uint32_t modPsizeBytes, /*!< [in] The modulus size in bytes. */ + uint8_t *orderQ_ptr, /*!< [in] The pointer to the prime order Q of generator. */ + uint32_t orderQsizeBytes, /*!< [in] The size of order of generator in bytes. */ + uint8_t *pubKey_ptr, /*!< [in] The pointer to the public key to be validated. */ + uint32_t pubKeySizeBytes, /*!< [in] The public key size in bytes. */ + CRYS_DH_Temp_t *tempBuff_ptr /*!< [in] The temp buffer for internal calculations. */ +); + + +#ifdef __cplusplus +} +#endif +/** +@} + */ +#endif diff --git a/features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_dh_error.h b/features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_dh_error.h new file mode 100644 index 00000000000..c9a7ff68001 --- /dev/null +++ b/features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_dh_error.h @@ -0,0 +1,158 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + + +#ifndef CRYS_DH_ERROR_H +#define CRYS_DH_ERROR_H + + +#include "crys_error.h" + + +#ifdef __cplusplus +extern "C" +{ +#endif + +/*! +@file +@brief This file contains error codes definitions for CRYS DH module. +@defgroup crys_dh_error CryptoCell DH specific errors +@{ +@ingroup crys_dh +*/ +/************************ Defines ******************************/ +/* DH module on the CRYS layer base address - 0x00F00500 */ +/*! The CRYS DH module errors */ +/*! Illegal input pointer.*/ +#define CRYS_DH_INVALID_ARGUMENT_POINTER_ERROR (CRYS_DH_MODULE_ERROR_BASE + 0x0UL) +/*! Illegal input size.*/ +#define CRYS_DH_INVALID_ARGUMENT_SIZE_ERROR (CRYS_DH_MODULE_ERROR_BASE + 0x1UL) +/*! Illegal operation mode.*/ +#define CRYS_DH_INVALID_ARGUMENT_OPERATION_MODE_ERROR (CRYS_DH_MODULE_ERROR_BASE + 0x2UL) +/*! Illegal hash mode.*/ +#define CRYS_DH_INVALID_ARGUMENT_HASH_MODE_ERROR (CRYS_DH_MODULE_ERROR_BASE + 0x3UL) + +/*! Illegal secret key data size. */ +#define CRYS_DH_SECRET_KEYING_DATA_SIZE_ILLEGAL_ERROR (CRYS_DH_MODULE_ERROR_BASE + 0x4UL) +/*! Illegal L input. */ +#define CRYS_DH_INVALID_L_ARGUMENT_ERROR (CRYS_DH_MODULE_ERROR_BASE + 0x5UL) +/*! Prime is smaller than generator. */ +#define CRYS_DH_ARGUMENT_PRIME_SMALLER_THAN_GENERATOR_ERROR (CRYS_DH_MODULE_ERROR_BASE + 0x6UL) +/*! Generator is smaller than zero. */ +#define CRYS_DH_ARGUMENT_GENERATOR_SMALLER_THAN_ZERO_ERROR (CRYS_DH_MODULE_ERROR_BASE + 0x7UL) +/*! Illegal private key size. */ +#define CRYS_DH_ARGUMENT_PRV_SIZE_ERROR (CRYS_DH_MODULE_ERROR_BASE + 0x8UL) +/*! Illegal buffer size. */ +#define CRYS_DH_ARGUMENT_BUFFER_SIZE_ERROR (CRYS_DH_MODULE_ERROR_BASE + 0x9UL) +/*! Invalid shared secret value. */ +#define CRYS_DH_INVALID_SHARED_SECRET_VALUE_ERROR (CRYS_DH_MODULE_ERROR_BASE + 0xAUL) +/*! DH is not supported. */ +#define CRYS_DH_IS_NOT_SUPPORTED (CRYS_DH_MODULE_ERROR_BASE + 0xFUL) +/*! Illegal X942 hybrid buffer size.*/ +#define CRYS_DH_X942_HYBRID_SIZE1_BUFFER_ERROR (CRYS_DH_MODULE_ERROR_BASE + 0x15UL) + +/*The requested derived secret key size is invalid*/ +/*! Illegal secret key size .*/ +#define CRYS_DH_SECRET_KEY_SIZE_NEEDED_ERROR (CRYS_DH_MODULE_ERROR_BASE + 0x16UL) +/*! Illegal output secret key size .*/ +#define CRYS_DH_SECRET_KEY_SIZE_OUTPUT_ERROR (CRYS_DH_MODULE_ERROR_BASE + 0x17UL) +/*! Illegal otherInfo size .*/ +#define CRYS_DH_OTHERINFO_SIZE_ERROR (CRYS_DH_MODULE_ERROR_BASE + 0x18UL) + +/* DH domain and key generation and checking errors */ +/*! Illegal modulus size. */ +#define CRYS_DH_INVALID_MODULUS_SIZE_ERROR (CRYS_DH_MODULE_ERROR_BASE + 0x20UL) +/*! Illegal order size. */ +#define CRYS_DH_INVALID_ORDER_SIZE_ERROR (CRYS_DH_MODULE_ERROR_BASE + 0x21UL) +/*! Illegal seed size. */ +#define CRYS_DH_INVALID_SEED_SIZE_ERROR (CRYS_DH_MODULE_ERROR_BASE + 0x22UL) +/*! Illegal J factor pointer size. */ +#define CRYS_DH_INVALID_J_FACTOR_PTR_OR_SIZE_ERROR (CRYS_DH_MODULE_ERROR_BASE + 0x23UL) +/*! Illegal generator pointer or size. */ +#define CRYS_DH_INVALID_GENERATOR_PTR_OR_SIZE_ERROR (CRYS_DH_MODULE_ERROR_BASE + 0x24UL) + +/*! Illegal domain primes. */ +#define CRYS_DH_CHECK_DOMAIN_PRIMES_NOT_VALID_ERROR (CRYS_DH_MODULE_ERROR_BASE + 0x25UL) +/*! Illegal domain generator. */ +#define CRYS_DH_CHECK_DOMAIN_GENERATOR_NOT_VALID_ERROR (CRYS_DH_MODULE_ERROR_BASE + 0x26UL) +/*! Illegal public key size. */ +#define CRYS_DH_INVALID_PUBLIC_KEY_SIZE_ERROR (CRYS_DH_MODULE_ERROR_BASE + 0x27UL) +/*! Illegal public key. */ +#define CRYS_DH_CHECK_PUB_KEY_NOT_VALID_ERROR (CRYS_DH_MODULE_ERROR_BASE + 0x28UL) +/*! Illegal generator size or pointer. */ +#define CRYS_DH_CHECK_GENERATOR_SIZE_OR_PTR_NOT_VALID_ERROR (CRYS_DH_MODULE_ERROR_BASE + 0x29UL) +/*! Illegal seed size or pointer. */ +#define CRYS_DH_CHECK_SEED_SIZE_OR_PTR_NOT_VALID_ERROR (CRYS_DH_MODULE_ERROR_BASE + 0x2AUL) +/*! Illegal generator. */ +#define CRYS_DH_CHECK_GENERATOR_NOT_VALID_ERROR (CRYS_DH_MODULE_ERROR_BASE + 0x2BUL) +/*! Prime generation failed. */ +#define CRYS_DH_PRIME_P_GENERATION_FAILURE_ERROR (CRYS_DH_MODULE_ERROR_BASE + 0x2CUL) +/*! Illegal public key. */ +#define CRYS_DH_INVALID_PUBLIC_KEY_ERROR (CRYS_DH_MODULE_ERROR_BASE + 0x2DUL) +/*! Illegal seed. */ +#define CRYS_DH_PASSED_INVALID_SEED_ERROR (CRYS_DH_MODULE_ERROR_BASE + 0x2EUL) +/*! Prime generation failed. */ +#define CRYS_DH_PRIME_Q_GENERATION_FAILURE_ERROR (CRYS_DH_MODULE_ERROR_BASE + 0x2FUL) +/*! Internal PKI error */ +#define CRYS_DH_PKI_INTERNAL_ERROR (CRYS_DH_MODULE_ERROR_BASE + 0x30UL) + + + +/************************ Enums ********************************/ + + +/************************ Typedefs ****************************/ + + +/************************ Structs ******************************/ + + +/************************ Public Variables **********************/ + + +/************************ Public Functions **********************/ + + + + +#ifdef __cplusplus +} +#endif +/** +@} + */ +#endif + diff --git a/features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_dh_kg.h b/features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_dh_kg.h new file mode 100644 index 00000000000..15654288f99 --- /dev/null +++ b/features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_dh_kg.h @@ -0,0 +1,203 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + + + +#ifndef _CRYS_DH_KG_H +#define _CRYS_DH_KG_H + + +#include "crys_dh.h" + + +#ifdef __cplusplus +extern "C" +{ +#endif + +/*! @file +@brief This module defines the API that supports Diffie-Hellman domain. +@defgroup crys_dh_kg CryptoCell DH Key Generation APIs +@{ +@ingroup crys_dh +*/ + +/************************ Defines ******************************/ +/*! Minimal size of DH seed in bytes. */ +#define CRYS_DH_SEED_MIN_SIZE_IN_BYTES CRYS_HASH_SHA1_DIGEST_SIZE_IN_BYTES +/*! Minimal size of DH seed in bits. */ +#define CRYS_DH_SEED_MIN_SIZE_IN_BITS (CRYS_DH_SEED_MIN_SIZE_IN_BYTES * 8) + +/************************ Enums ********************************/ + + +/************************ Typedefs ****************************/ + +/* temp buffers, used in different DH KG functions */ + +/*! Temporary data buffer structure for domain parameters generation in DH. */ +typedef struct CRYS_DHKGData_t +{ + /* The aligned input and output temp buffers */ + /*! Temporary buffer. */ + uint32_t TempBuff1[CRYS_DH_MAX_MOD_BUFFER_SIZE_IN_WORDS]; + /*! Temporary buffer. */ + uint32_t TempBuff2[CRYS_DH_MAX_MOD_BUFFER_SIZE_IN_WORDS]; + /*! Temporary buffer. */ + uint32_t TempBuff3[CRYS_DH_MAX_MOD_BUFFER_SIZE_IN_WORDS]; + /*! Temporary buffer. */ + uint32_t TempBuff4[CRYS_DH_MAX_MOD_BUFFER_SIZE_IN_WORDS]; + /*! Temporary buffer. */ + uint32_t TempBuff5[CRYS_DH_MAX_MOD_BUFFER_SIZE_IN_WORDS]; + /*! Temporary buffer. */ + uint32_t TempBuff6[CRYS_DH_MAX_MOD_BUFFER_SIZE_IN_WORDS]; + /*! Temporary buffer. */ + CRYS_DH_Temp_t ExpTemps; +}CRYS_DHKGData_t; + +/*! Temporary buffer structure . */ +typedef struct CRYS_DHKG_CheckTemp_t +{ + /*! Temporary buffer. */ + uint32_t CheckTempBuff[3*CRYS_DH_MAX_MOD_BUFFER_SIZE_IN_WORDS]; + /*! Temporary buffer. */ + CRYS_DHKGData_t DhKgBuff; +}CRYS_DHKG_CheckTemp_t; + +/*! DH Domain generation values definitions */ +/*! Minimal modulus size for X942 - 1024.*/ +#define DH_X942_PRIME_MOD_MIN_VAL 1024 +/*! Maximal modulus size for X942 - 2048.*/ +#define DH_X942_PRIME_MOD_MAX_VAL 2048 +/*! PGeneration counter for X942 - 4096.*/ +#define DH_X942_PGEN_COUNTER_CONST 4096 +/*! HASH size in bits for X942 - 160.*/ +#define DH_X942_HASH_SIZE_BITS 160 +/*! Maximal allowed ratio between modulus and generator order sizes (by implementation) */ +#define DH_MAX_RATIO_MODULO_TO_ORDER 4 + +/************************ Structs ******************************/ + +/************************ Public Variables **********************/ + +/************************ Public Functions **********************/ + + +/******************************************************************************************/ +/*! +@brief This function generates DH domain parameters in Galois prime field according to standard [ANS X9.42]. +It receives the required sizes (in bits) of the modulus, the generator's order, and the seed, and then generates +the prime modulus and the generator according to given sizes. +If generateSeed argument is set to 1, the function generates and outputs the random seed. Otherwise (if set to 0), +the seed has to be passed as an input argument. According to implementation the seed should be not greate, than (2^seedSizeBits - 2^32). +The seed and some additional parameters, generated by the function (factorJ, pgenCounter), are used for checking +that all domain parameters are generated according to the standard and not forged. +\note All buffer parameters should be in Big-Endian form. + +@return CRYS_OK on success. +@return A non-zero value on failure as defined crys_dh_error.h, crys_rnd_error.h or crys_hash_error.h. +*/ +CIMPORT_C CRYSError_t CRYS_DH_CreateDomainParams( + void *rndState_ptr, /*!< [in/out] Pointer to the RND state structure. */ + SaSiRndGenerateVectWorkFunc_t rndGenerateVectFunc, /*!< [in] Pointer to a random vector generation function. */ + uint32_t modPsizeBits, /*!< [in] Size of the modulus (Prime) in bits equal 256*n, where n >= 4. FIPS 186-4 + defines sizes 1024 and 2048 bit. */ + uint32_t orderQsizeBits, /*!< [in] Size of the Generator's order in bits. FIPS 186-4 defines orderQSizeBits = 160 + for modulus 1024 bit and 224 or 256 bit for modPSizeBits = 2048. We not recommend + sizes > 256 and returns an error if orderQSizeBits > modPSizeBits/4 */ + uint32_t seedSizeBits, /*!< [in] Seed size in bits. Requirements: modPSizeBits >= seedSizeBits >= orderQSizeBits + (the first is required by our implementation). */ + uint8_t *modP_ptr, /*!< [out] Pointer to the modulus (prime) buffer. The size of the buffer for output + generated value must be no less than given modulus size. */ + uint8_t *orderQ_ptr, /*!< [out] Pointer to the order Q of generator. The size of the buffer for output generated + value must be no less than the given order size. */ + uint8_t *generatorG_ptr, /*!< [out] Pointer to the generator of multiplicative subgroup in GF(P). + If the user does not need this output, then both the pointer and the buffer size + must be set to 0. */ + uint32_t *generGsizeBytes_ptr, /*!< [in/out] Pointer to the one word buffer for outputting the generator's size. + The passed size (if needed) must be not less than modulus size and the function + returns the actual size of the generator. */ + uint8_t *factorJ_ptr, /*!< [out] Pointer to the buffer for integer factor J. If NULL, the function does not output + this parameter (in this case JsizeBytes_ptr also must be set to NULL, else the function + returns an error). */ + uint32_t *JsizeBytes_ptr, /*!< [in/out] Pointer to the size of integer factor J. If NULL, the function does not output + this parameter. */ + uint8_t *seedS_ptr, /*!< [in/out] Random seed used for prime generation. The size of the buffer must be + at least the seed size. */ + int8_t generateSeed, /*!< [in] Flag, defining whether the seed should be generated randomly by the function + (1) or is passed by the user (0). */ + uint32_t *pgenCounter_ptr, /*!< [out] Pointer to counter of tries to generate the primes. If NULL, the function does not + output this parameter. */ + CRYS_DHKGData_t *DHKGbuff_ptr /*!< [out] The temp buffer of defined structure for internal calculations. */ +); + + +/******************************************************************************************/ +/*! +@brief This function receives DH domain parameters, seed and prime generation counter and then verifies +that the domain was created according to the standard [ANS X9.42]. +According to implementation, the value of the user passed seed should be not +greate, than (2^seedSizeBits - 2^32), otherwise an error is returned. +\note All buffer parameters should be in Big-Endian form. For more detailed +description of the parameters see ::CRYS_DH_CreateDomainParams. + +@return CRYS_OK on success. +@return A non-zero value on failure as defined crys_dh_error.h, crys_rnd_error.h or crys_hash_error.h. +*/ +CIMPORT_C CRYSError_t CRYS_DH_CheckDomainParams( + void *rndState_ptr, /*!< [in/out] Pointer to the RND state. */ + SaSiRndGenerateVectWorkFunc_t rndGenerateVectFunc, /*!< [in/out] Pointer to the RND Generate vector function pointer. */ + uint8_t *modP_ptr, /*!< [in] Pointer to the modulus (Prime). */ + uint32_t modPsizeBytes, /*!< [in] Size of the modulus (Prime) in bytes. */ + uint8_t *orderQ_ptr, /*!< [in] Pointer to the order Q of generator. The size of the buffer for output + generated value must be no less than the order size. */ + uint32_t orderQsizeBytes, /*!< [in] Size of the Generator's order in bytes. */ + uint8_t *generatorG_ptr, /*!< [in] Pointer to the generator of the multiplicative subgroup in GF(P). */ + uint32_t generatorSizeBytes, /*!< [in] Size of the generator in bytes. */ + uint8_t *seedS_ptr, /*!< [in] Random seed used for prime generation. */ + uint32_t seedSizeBits, /*!< [in] Seed size in bits. */ + uint32_t pgenCounter, /*!< [in] Counter of prime generation attempts. */ + CRYS_DHKG_CheckTemp_t *checkTempBuff_ptr /*!< [in] Temporary buffer for internal calculations. */ + +); + + +#ifdef __cplusplus +} +#endif +/** +@} + */ +#endif diff --git a/features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_ec_edw_api.h b/features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_ec_edw_api.h new file mode 100644 index 00000000000..6d544713079 --- /dev/null +++ b/features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_ec_edw_api.h @@ -0,0 +1,201 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + + +#ifndef CRYS_EC_EDW_API_H +#define CRYS_EC_EDW_API_H + +#include "ssi_pal_types.h" +#include "crys_hash.h" +#include "crys_rnd.h" +#include "crys_pka_defs_hw.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/*! +@defgroup cryptocell_ec CryptoCell EC 25519 curve APIs +@{ +@ingroup cryptocell_api +@brief This group is the cryptocell EC 25519 curve root group +@} + +@file +@brief This file contains the CRYS APIs used for EC EDW (Edwards) ed25519 algorithms. +@defgroup crys_ec_edw CryptoCell EC Edwards APIs +@{ +@ingroup cryptocell_ec + +\note Algorithms of Montgomery and Edwards elliptic curves cryptography were developed by + Daniel.J.Bernstein. +*/ + +/*! EC Edwards ed25519 modulus and order sizes in bits, words and bytes. */ +/*! EC Edwards modulus size in bits. */ +#define CRYS_ECEDW_MOD_SIZE_IN_BITS 255U /*!<\internal MOD - EC Edw modulus size*/ +/*! EC Edwards order size in bits. */ +#define CRYS_ECEDW_ORD_SIZE_IN_BITS 255U /*!<\internal ORD - EC Edw generator order size*/ +/*! EC Edwards nodulus size in words. */ +#define CRYS_ECEDW_MOD_SIZE_IN_32BIT_WORDS ((CRYS_ECEDW_MOD_SIZE_IN_BITS + SASI_BITS_IN_32BIT_WORD - 1) / SASI_BITS_IN_32BIT_WORD) +/*! EC Edwards modulus size in bytes. */ +#define CRYS_ECEDW_MOD_SIZE_IN_BYTES (CRYS_ECEDW_MOD_SIZE_IN_32BIT_WORDS * SASI_32BIT_WORD_SIZE) +/*! EC Edwards order size in words. */ +#define CRYS_ECEDW_ORD_SIZE_IN_32BIT_WORDS ((CRYS_ECEDW_ORD_SIZE_IN_BITS + SASI_BITS_IN_32BIT_WORD - 1) / SASI_BITS_IN_32BIT_WORD) +/*! EC Edwards order size in bytes. */ +#define CRYS_ECEDW_ORD_SIZE_IN_BYTES (CRYS_ECEDW_ORD_SIZE_IN_32BIT_WORDS * SASI_32BIT_WORD_SIZE) + +/*! Constant sizes of special EC_MONT buffers and arrays */ +/*! EC Edwards seed size in bytes. */ +#define CRYS_ECEDW_SEED_BYTES CRYS_ECEDW_MOD_SIZE_IN_BYTES +/*! EC Edwards secret key size in bytes. */ +#define CRYS_ECEDW_SECRET_KEY_BYTES (2 * CRYS_ECEDW_MOD_SIZE_IN_BYTES) +/*! EC Edwards signatue size in bytes. */ +#define CRYS_ECEDW_SIGNATURE_BYTES (2 * CRYS_ECEDW_ORD_SIZE_IN_BYTES) +/*! EC Edwards scalar size in bytes. */ +#define CRYS_ECEDW_SCALAR_BYTES CRYS_ECEDW_ORD_SIZE_IN_BYTES +/*! EC Edwards scalar multiplication size in bytes. */ +#define CRYS_ECEDW_SCALARMULT_BYTES CRYS_ECEDW_MOD_SIZE_IN_BYTES + +/*! EC_EDW temp buffer size definition. */ +#define CRYS_ECEDW_TEMP_BUFF_SIZE_IN_32BIT_WORD (10*CRYS_EC_MONT_EDW_MODULUS_MAX_SIZE_IN_WORDS + (sizeof(CRYS_HASHUserContext_t)+SASI_32BIT_WORD_SIZE-1)/SASI_32BIT_WORD_SIZE) + +/*! EC_EDW temp buffer type definition. */ +typedef struct { + /*! Internal buffer. */ + uint32_t buff[CRYS_ECEDW_TEMP_BUFF_SIZE_IN_32BIT_WORD]; +} CRYS_ECEDW_TempBuff_t; + + +/******************************************************************************/ +/*! +@brief The function creates EC Edwards signature on the message. +\note Used detached form of signature, separated from the message. + Implemented algorithm of Bernstein D. etc. sign ed25519. + +@return CRYS_OK on success, +@return A non-zero value on failure as defined crys_ec_mont_edw_error.h or crys_hash_error.h. +*/ +CIMPORT_C CRYSError_t CRYS_ECEDW_Sign ( + uint8_t *pSign, /*!< [out] Pointer to the detached signature. */ + size_t *pSignSize, /*!< [in/out] Pointer to the total size of the signature ; + In - the buffer size, which (must be at least 2*EC order size); + Out - the actual size of output data. */ + const uint8_t *pMsg, /*!< [in] Pointer to the message. */ + size_t msgSize, /*!< [in] Message size in bytes: must be less, than + (CRYS_HASH_UPDATE_DATA_MAX_SIZE_IN_BYTES - 2*(EC_EDW modulus size)). */ + const uint8_t *pSignSecrKey, /*!< [in] Pointer to the signer secret key (seed || pulKey) */ + size_t secrKeySize, /*!< [in] Size of signer secret key in bytes: (must be 2*EC order size). */ + CRYS_ECEDW_TempBuff_t *pTempBuff /*!< [in] Pointer to the temp buffer. */); + + + +/******************************************************************************/ +/*! +@brief The function verifies the EC Edwards ed25519 signature on the message. +\note The input signature is in detached form, i.e. separated from the message. + +@return CRYS_OK on success, +@return A non-zero value on failure as defined crys_ec_mont_edw_error.h or crys_hash_error.h. +*/ +CIMPORT_C CRYSError_t CRYS_ECEDW_Verify( + const uint8_t *pSign, /*!< [in] Pointer to detached signature, i.e. the + signature is separated from the message. */ + size_t signSize, /*!< [in] Size of the signature in bytes, it must be + equal to two EC Order size in bytes. */ + const uint8_t *pSignPublKey, /*!< [in] Pointer to signer public key. */ + size_t publKeySize, /*!< [in] Size of the signer public key in bytes; must be + equal to EC modulus size. */ + uint8_t *pMsg, /*!< [in] Pointer to the message. */ + size_t msgSize, /*!< [in] Pointer to the message size in bytes. Must be less than + (CRYS_HASH_UPDATE_DATA_MAX_SIZE_IN_BYTES - 2*(EC_EDW modulus size)). */ + CRYS_ECEDW_TempBuff_t *pTempBuff /*!< [in] Pointer to the temp buffer, for internal use. */); + + +/******************************************************************************/ +/*! +@brief The function randomly generates Ec ed25519 private and public keys + using given seed. + The generation is performed using EC Edwards ed25519 algorithm. + +@return CRYS_OK on success, +@return A non-zero value on failure as defined crys_ec_mont_edw_error.h or crys_hash_error.h. +*/ +CIMPORT_C CRYSError_t CRYS_ECEDW_SeedKeyPair ( + const uint8_t *pSeed, /*!< [in] Pointer to the given seed. */ + size_t seedSize, /*!< [in] Size of the seed in bytes, must be equal the EC order size + in bytes. */ + uint8_t *pSecrKey, /*!< [out] Pointer to the secret key, including the seed, concatenated + with the public key. */ + size_t *pSecrKeySize, /*!< [in/out] Pointer to the size of the secret key buffer in bytes + (must be at least 2*EC order size). */ + uint8_t *pPublKey, /*!< [out] Pointer to the public key. */ + size_t *pPublKeySize, /*!< [in/out] Pointer to the size of the public key in bytes. + In - the size of buffer must be at least EC modulus size; + Out - the actual size. */ + CRYS_ECEDW_TempBuff_t *pTempBuff /*!< [in] Pointer to the temp buffer, for internal use. */); + +/*******************************************************************/ +/*! + @brief The function randomly generates the EC Edwards ed25519 private and + public keys. + The generation is performed using EC Edwards ed25519 algorithm. + +@return CRYS_OK on success, +@return A non-zero value on failure as defined crys_ec_mont_edw_error.h, crys_hash_error.h or crys_rnd_error. +*/ +CIMPORT_C CRYSError_t CRYS_ECEDW_KeyPair ( + uint8_t *pSecrKey, /*!< [out] Pointer to the secret key (including seed and public key). */ + size_t *pSecrKeySize, /*!< [in/out] Pointer to the size of the secret key in bytes, + (must be at least 2*EC order size). */ + uint8_t *pPublKey, /*!< [out] Pointer to the public key. */ + size_t *pPublKeySize, /*!< [in/out] - Pointer to the size of the public key in bytes. + In - the size of buffer must be at least EC modulus size; + Out - the actual size. */ + void *pRndState, /*!< [in/out] Pointer to the RND state structure. */ + SaSiRndGenerateVectWorkFunc_t rndGenerateVectFunc, /*!< [in] Pointer to the random vector generation function. */ + CRYS_ECEDW_TempBuff_t *pTempBuff /*!< [in] Pointer to the temp buffer. */); + + +#ifdef __cplusplus +} +#endif +/** +@} + */ +#endif + + + diff --git a/features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_ec_mont_api.h b/features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_ec_mont_api.h new file mode 100644 index 00000000000..57ab9d78baf --- /dev/null +++ b/features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_ec_mont_api.h @@ -0,0 +1,213 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + + +#ifndef CRYS_ECMONT_API_H +#define CRYS_ECMONT_API_H + +#include "ssi_pal_types.h" +#include "crys_rnd.h" +#include "crys_pka_defs_hw.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/*! +@file +@brief This file contains the CRYS APIs used for EC MONT (Montgomery Curve25519) algorithms. +@defgroup crys_ec_mont CryptoCell EC Montgomery APIs +@{ +@ingroup cryptocell_ec + + +\note Implemented algorithms according to Montgomery elliptic curves cryptography, + developed by Daniel J.Bernstein etc. +*/ + +/*! EC Montgomery curve25519 modulus size in bits, words and bytes */ +/*! EC Montgomery modulus size in bits. */ +#define CRYS_ECMONT_MOD_SIZE_IN_BITS 255U +/*! EC Montgomery modulus size in words. */ +#define CRYS_ECMONT_MOD_SIZE_IN_32BIT_WORDS ((CRYS_ECMONT_MOD_SIZE_IN_BITS + SASI_BITS_IN_32BIT_WORD - 1) / SASI_BITS_IN_32BIT_WORD) +/*! EC Montgomery modulus size in bytes. */ +#define CRYS_ECMONT_MOD_SIZE_IN_BYTES ((CRYS_ECMONT_MOD_SIZE_IN_BITS + SASI_BITS_IN_32BIT_WORD - 1) / sizeof(uint32_t)) + +/*! Constant sizes of special EC_MONT buffers and arrays */ +/*! EC Montgomery scalar size in bytes. */ +#define CRYS_ECMONT_SCALARBYTES (CRYS_ECMONT_MOD_SIZE_IN_32BIT_WORDS * SASI_32BIT_WORD_SIZE) +/*! EC Montgomery scalar multiplication size in bytes. */ +#define CRYS_ECMONT_SCALARMULTBYTES (CRYS_ECMONT_MOD_SIZE_IN_32BIT_WORDS * SASI_32BIT_WORD_SIZE) +/*! EC Montgomery scalar seed size in bytes. */ +#define CRYS_ECMONT_SEEDBYTES (CRYS_ECMONT_MOD_SIZE_IN_32BIT_WORDS * SASI_32BIT_WORD_SIZE) + +/*! EC Montgomery domains ID-s enumerator. */ +typedef enum { + CRYS_ECMONT_DOMAIN_CURVE_25519, /*!< EC Curve25519. */ + /*! EC Montgomery last domain. */ + CRYS_ECMONT_DOMAIN_OFF_MODE, + /*! Reserved. */ + CRYS_ECMONT_DOMAIN_LAST = 0x7FFFFFFF +}CRYS_ECMONT_DomainId_t; + + +/*! EC_MONT scalar mult temp buffer type definition */ +typedef struct { + /*! Internal temporary buffer. */ + uint32_t ecMontScalarMultTempBuff[CRYS_EC_MONT_TEMP_BUFF_SIZE_IN_32BIT_WORDS]; // set needed +} CRYS_ECMONT_ScalrMultTempBuff_t; + +/*! EC_MONT temp buffer type definition */ +typedef struct { + /* Don't change sequence order of the buffers */ + /*! Internal temporary buffer. */ + uint32_t ecMontScalar[CRYS_EC_MONT_EDW_MODULUS_MAX_SIZE_IN_WORDS]; + /*! Internal temporary buffer. */ + uint32_t ecMontResPoint[CRYS_EC_MONT_EDW_MODULUS_MAX_SIZE_IN_WORDS]; + /*! Internal temporary buffer. */ + uint32_t ecMontInPoint[CRYS_EC_MONT_EDW_MODULUS_MAX_SIZE_IN_WORDS]; + /*! Internal temporary buffer. */ + CRYS_ECMONT_ScalrMultTempBuff_t ecMontScalrMultTempBuff; // if needed +} CRYS_ECMONT_TempBuff_t; + + +/*********************************************************************/ +/*! +@brief The function performs EC Montgomery (Curve25519) scalar multiplication: + resPoint = scalar * point. + +@return CRYS_OK on success, +@return A non-zero value on failure as defined crys_ec_mont_edw_error.h. +*/ +CIMPORT_C CRYSError_t CRYS_ECMONT_Scalarmult( + uint8_t *pResPoint, /*!< [out] Pointer to the public (secret) key. */ + size_t *pResPointSize, /*!< [in/out] Pointer to the size of the public key in bytes. + In - the size of the buffer. must be at least EC modulus + size (for curve25519 - 32 bytes). + Out - the actual size. */ + const uint8_t *pScalar, /*!< [in] Pointer to the secret (private) key. */ + size_t scalarSize, /*!< [in] Pointer to the size of the secret key in bytes; + must be equal to EC order size (for curve25519 - 32 bytes). */ + const uint8_t *pInPoint, /*!< [in] Pointer to the input point (compressed). */ + size_t inPointSize, /*!< [in] Size of the point - must be equal to CRYS_ECMONT_MOD_SIZE_IN_BYTES. */ + CRYS_ECMONT_TempBuff_t *pEcMontTempBuff /*!< [in] Pointer to temp buffer, for internal use. */); + + +/*********************************************************************/ +/*! +@brief The function performs EC Montgomery (Curve25519) scalar multiplication of base point: + res = scalar * base_point. + + Note: all byte arrays have LE order of bytes, i.e. LS byte is on left most place. + +@return CRYS_OK on success, +@return A non-zero value on failure as defined crys_ec_mont_edw_error.h. +*/ +CIMPORT_C CRYSError_t CRYS_ECMONT_ScalarmultBase( + uint8_t *pResPoint, /*!< [out] Pointer to the public (secret) key. */ + size_t *pResPointSize, /*!< [in/out] Pointer to the size of the public key in bytes. + In - the size of buffer must be at least EC modulus size + (for curve25519 - 32 bytes); + Out - the actual size. */ + const uint8_t *pScalar, /*!< [in] Pointer to the secret (private) key. */ + size_t scalarSize, /*!< [in] Pointer to the size of the scalar in bytes - + must be equal to EC order size (for curve25519 - 32 bytes). */ + CRYS_ECMONT_TempBuff_t *pEcMontTempBuff /*!< [in] Pointer to temp buffer, for internal use. */); + + +/*******************************************************************/ +/*! +@brief The function randomly generates private and public keys for Montgomery + Curve25519. + + +\note
  • All byte arrays are in LE order of bytes, i.e. LS byte is on the left most place.
  • +
  • LS and MS bits of the Secret key are set according to EC Montgomery scalar mult. algorithm: + secrKey[0] &= 248; secrKey[31] &= 127; secrKey[31] |= 64;
+ +@return CRYS_OK on success, +@return A non-zero value on failure as defined crys_ec_mont_edw_error.h or crys_rnd_error.h. + +*/ +CIMPORT_C CRYSError_t CRYS_ECMONT_KeyPair ( + uint8_t *pPublKey, /*!< [out] Pointer to the public key. */ + size_t *pPublKeySize, /*!< [in/out] Pointer to the size of the public key in bytes. + In - the size of the buffer must be at least EC order size + (for curve25519 - 32 bytes); + Out - the actual size. */ + uint8_t *pSecrKey, /*!< [out] Pointer to the secret key, including. */ + size_t *pSecrKeySize, /*!< [in/out] Pointer to the size of buffer for the secret key in bytes - + must be at least EC order size (for curve25519 - 32 bytes). */ + void *pRndState, /*!< [in/out] Pointer to the RND state structure. */ + SaSiRndGenerateVectWorkFunc_t rndGenerateVectFunc, /*!< [in] Pointer to the random vector generation function. */ + CRYS_ECMONT_TempBuff_t *pEcMontTempBuff /*!< [in] Pointer to the temp buffer, for internal use. */); + + +/*******************************************************************/ +/*! +@brief The function generates private and public keys for Montgomery algorithms. + + The generation performed using given seed. + + +@return CRYS_OK on success, +@return A non-zero value on failure as defined crys_ec_mont_edw_error.h or crys_hash_error.h. +*/ +CIMPORT_C CRYSError_t CRYS_ECMONT_SeedKeyPair ( + uint8_t *pPublKey, /*!< [out] Pointer to the public (secret) key. */ + size_t *pPublKeySize, /*!< [in/out] Pointer to the size of the public key in bytes. + In - the size of buffer must be at least EC order size + (for curve25519 - 32 bytes); + Out - the actual size. */ + uint8_t *pSecrKey, /*!< [out] Pointer to the secret (private) key. */ + size_t *pSecrKeySize, /*!< [in/out] Pointer to the size of the secret key in bytes + In - the size of buffer must be at least EC order size + (for curve25519 - 32 bytes); + Out - the actual size. */ + const uint8_t *pSeed, /*!< [in] Pointer to the given seed - 32 bytes. */ + size_t seedSize, /*!< [in/] Size of the seed in bytes (must be equal to CRYS_ECMONT_SEEDBYTES). */ + CRYS_ECMONT_TempBuff_t *pEcMontTempBuff /*!< [in] Pointer to a temp buffer, for internal use. */); + + +#ifdef __cplusplus +} +#endif +/** +@} + */ +#endif + + + diff --git a/features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_ec_mont_edw_error.h b/features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_ec_mont_edw_error.h new file mode 100644 index 00000000000..5b76d2cc40b --- /dev/null +++ b/features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_ec_mont_edw_error.h @@ -0,0 +1,114 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + +#ifndef CRYS_EC_MONT_EDW_ERROR_H +#define CRYS_EC_MONT_EDW_ERROR_H + +/*! +@file +@brief This module containes the definitions of the CRYS ECC-25519 errors. +@defgroup crys_ecmontedw_error CryptoCell ECC-25519 errors +@{ +@ingroup cryptocell_ec +*/ + +#include "crys_error.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + + +/************************ Defines ******************************/ + +/********************************************************************************************************** + * CRYS EC Montgomery-Edwards MODULE ERRORS base address - 0x00F02300 * + **********************************************************************************************************/ +/*! Illegal input pointer */ +#define CRYS_ECEDW_INVALID_INPUT_POINTER_ERROR (CRYS_EC_MONT_EDW_MODULE_ERROR_BASE + 0x00UL) +/*! Illegal input size */ +#define CRYS_ECEDW_INVALID_INPUT_SIZE_ERROR (CRYS_EC_MONT_EDW_MODULE_ERROR_BASE + 0x01UL) +/*! Illegal scalar size */ +#define CRYS_ECEDW_INVALID_SCALAR_SIZE_ERROR (CRYS_EC_MONT_EDW_MODULE_ERROR_BASE + 0x02UL) +/*! Illegal scalar data */ +#define CRYS_ECEDW_INVALID_SCALAR_DATA_ERROR (CRYS_EC_MONT_EDW_MODULE_ERROR_BASE + 0x03UL) +/*! Invalid RND context pointer */ +#define CRYS_ECEDW_RND_CONTEXT_PTR_INVALID_ERROR (CRYS_EC_MONT_EDW_MODULE_ERROR_BASE + 0x04UL) +/*! Invalid RND generate vector functions pointer */ +#define CRYS_ECEDW_RND_GEN_VECTOR_FUNC_ERROR (CRYS_EC_MONT_EDW_MODULE_ERROR_BASE + 0x05UL) +/*! Signing or verification operation failed */ +#define CRYS_ECEDW_SIGN_VERIFY_FAILED_ERROR (CRYS_EC_MONT_EDW_MODULE_ERROR_BASE + 0x20UL) +/*! Illegal input pointer */ +#define CRYS_ECMONT_INVALID_INPUT_POINTER_ERROR (CRYS_EC_MONT_EDW_MODULE_ERROR_BASE + 0x30UL) +/*! Illegal input size */ +#define CRYS_ECMONT_INVALID_INPUT_SIZE_ERROR (CRYS_EC_MONT_EDW_MODULE_ERROR_BASE + 0x31UL) +/*! Illegal domain id */ +#define CRYS_ECMONT_INVALID_DOMAIN_ID_ERROR (CRYS_EC_MONT_EDW_MODULE_ERROR_BASE + 0x32UL) +/*! Internal PKI error */ +#define CRYS_ECEDW_PKI_ERROR (CRYS_EC_MONT_EDW_MODULE_ERROR_BASE + 0x33UL) +/*! Internal PKI error */ +#define CRYS_ECMONT_PKI_ERROR (CRYS_EC_MONT_EDW_MODULE_ERROR_BASE + 0x34UL) + + +/************************************************************************************************************ + * NOT SUPPORTED MODULES ERROR IDs * + ************************************************************************************************************/ +/*! EC montgomery is not supported */ +#define CRYS_ECMONT_IS_NOT_SUPPORTED (CRYS_EC_MONT_EDW_MODULE_ERROR_BASE + 0xFEUL) +/*! EC edwards is not supported */ +#define CRYS_ECEDW_IS_NOT_SUPPORTED (CRYS_EC_MONT_EDW_MODULE_ERROR_BASE + 0xFFUL) + + + +/************************ Enums ********************************/ + +/************************ Typedefs ****************************/ + +/************************ Structs ******************************/ + +/************************ Public Variables **********************/ + +/************************ Public Functions **********************/ + +#ifdef __cplusplus +} +#endif +/** +@} +*/ +#endif + + diff --git a/features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_ecpki_build.h b/features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_ecpki_build.h new file mode 100644 index 00000000000..72391ab710e --- /dev/null +++ b/features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_ecpki_build.h @@ -0,0 +1,207 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + +#ifndef CRYS_ECPKI_BUILD_H +#define CRYS_ECPKI_BUILD_H + +/*! +@defgroup cryptocell_ecpki CryptoCell ECC APIs +@{ +@ingroup cryptocell_api +@brief This group is the cryptocell ECC root group +@} + +@file +@brief This module defines functions for building key structures used in Elliptic Curves Cryptography (ECC). +@defgroup crys_ecpki_build CryptoCell key build for ECC APIs +@{ +@ingroup cryptocell_ecpki +*/ + + +#include "crys_error.h" +#include "crys_ecpki_types.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/********************************************************************************** + * CRYS_ECPKI_BuildPrivKey function * + **********************************************************************************/ +/*! +@brief Builds (imports) the user private key structure from an existing private key so +that this structure can be used by other EC primitives. +This function should be called before using of the private key. Input +domain structure must be initialized by EC parameters and auxiliary +values, using CRYS_ECPKI_GetDomain or CRYS_ECPKI_SetDomain functions. + +@return CRYS_OK on success. +@return A non-zero value on failure as defined crys_ecpki_error.h. +*/ +CIMPORT_C CRYSError_t CRYS_ECPKI_BuildPrivKey( + const CRYS_ECPKI_Domain_t *pDomain, /*!< [in] The EC domain (curve). */ + const uint8_t *pPrivKeyIn, /*!< [in] Pointer to private key data. */ + uint32_t PrivKeySizeInBytes, /*!< [in] Size of private key data (in bytes). */ + CRYS_ECPKI_UserPrivKey_t *pUserPrivKey /*!< [out] Pointer to the private key structure. + This structure is used as input to the ECPKI cryptographic primitives. */ + ); + +/********************************************************************************** + * _DX_ECPKI_BuildPublKey function * + **********************************************************************************/ +/*! +@brief Builds a user public key structure from an imported public key, +so it can be used by other EC primitives. +When operating the EC cryptographic algorithms with imported EC public +key, this function should be called before using of the public key. + +\note The Incoming public key PublKeyIn structure is big endian bytes array, containing +concatenation of PC||X||Y, where: +
  • PC - point control single byte, defining the type of point: 0x4 - uncompressed, +06,07 - hybrid, 2,3 - compressed.
  • +
  • X,Y - EC point coordinates of public key (y is omitted in compressed form), +size of X and Y must be equal to size of EC modulus.
+ +The user may call this function by appropriate macros, according to necessary validation level [SEC1. ECC standard: 3.2, ANS X9.62]: +
  • Checking the input pointers and sizes only - ::CRYS_ECPKI_BuildPublKey.
  • +
  • Partially checking of public key - ::CRYS_ECPKI_BuildPublKeyPartlyCheck.
  • +
  • Full checking of public key - ::CRYS_ECPKI_BuildPublKeyFullCheck.
+ +\note Full check mode takes long time and should be used when it is actually needed. + +@return CRYS_OK on success. +@return A non-zero value on failure as defined crys_ecpki_error.h. +*/ +/* +The function performs the following operations: +- Checks validity of incoming variables and pointers; +- Converts incoming key data from big endian into little endian; +- If public key is given in compressed form (i.e. byte[0] = 2 or 3 and + coordinate Y is omitted), then the function uncompress it; +- Performs checking of input key according to CheckMode parameter. +- Initializes variables and structures. +*/ +CIMPORT_C CRYSError_t _DX_ECPKI_BuildPublKey( + const CRYS_ECPKI_Domain_t *pDomain, /*!< [in] The EC domain (curve). */ + uint8_t *PublKeyIn_ptr, /*!< [in] Pointer to the input public key data, in compressed or + uncompressed or hybrid form: + [PC||X||Y] Big-Endian representation, structured according to + [IEEE1363], where: +
  • X and Y are the public key's EC point coordinates. + In compressed form, Y is omitted.
  • +
  • The sizes of X and Y are equal to the size of the EC modulus.
  • +
  • PC is a one-byte point control that defines the type of point + compression.
*/ + uint32_t PublKeySizeInBytes, /*!< [in] The size of public key data (in bytes). */ + EC_PublKeyCheckMode_t CheckMode, /*!< [in] The required level of public key verification + (higher verification level means longer verification time): +
  • 0 = preliminary validation.
  • +
  • 1 = partial validation.
  • +
  • 2 = full validation.
*/ + CRYS_ECPKI_UserPublKey_t *pUserPublKey, /*!< [out] Pointer to the output public key structure. + This structure is used as input to the ECPKI cryptographic primitives. */ + CRYS_ECPKI_BUILD_TempData_t *pTempBuff /*!< [in] Pointer for a temporary buffer required for the build function. */ + ); + + +/********************************************************************************** + * CRYS_ECPKI_BuildPublKey macro * + **********************************************************************************/ +/*! +@brief This macro calls _DX_ECPKI_BuildPublKey function for building the public key +while checking input pointers and sizes. For a description of the parameters see ::_DX_ECPKI_BuildPublKey. +*/ +#define CRYS_ECPKI_BuildPublKey(pDomain, PublKeyIn_ptr, PublKeySizeInBytes, pUserPublKey) \ + _DX_ECPKI_BuildPublKey((pDomain), (PublKeyIn_ptr), (PublKeySizeInBytes), CheckPointersAndSizesOnly, (pUserPublKey), NULL) + + +/********************************************************************************** + * CRYS_ECPKI_BuildPublKeyPartlyCheck macro * + **********************************************************************************/ +/*! +@brief This macro calls _DX_ECPKI_BuildPublKey function for building the public key with partial validation of the key [SEC1] - 3.2.3. +For a description of the parameters see ::_DX_ECPKI_BuildPublKey. +*/ +#define CRYS_ECPKI_BuildPublKeyPartlyCheck(pDomain, PublKeyIn_ptr, PublKeySizeInBytes, pUserPublKey, pTempBuff) \ + _DX_ECPKI_BuildPublKey((pDomain), (PublKeyIn_ptr), (PublKeySizeInBytes), ECpublKeyPartlyCheck, (pUserPublKey), (pTempBuff)) + + +/********************************************************************************** + * CRYS_ECPKI_BuildPublKeyFullCheck macro * + **********************************************************************************/ +/*! +@brief This macro calls _DX_ECPKI_BuildPublKey function for building the public key with full validation of the key [SEC1] - 3.2.2. +For a description of the parameters and return values see _DX_ECPKI_BuildPublKey. +*/ +#define CRYS_ECPKI_BuildPublKeyFullCheck(pDomain, PublKeyIn_ptr, PublKeySizeInBytes, pUserPublKey, pTempBuff) \ + _DX_ECPKI_BuildPublKey((pDomain), (PublKeyIn_ptr), (PublKeySizeInBytes), (ECpublKeyFullCheck), (pUserPublKey), (pTempBuff)) + + +/*********************************************************************************** + * CRYS_ECPKI_ExportPublKey function * + ***********************************************************************************/ +/*! +@brief Converts an existing public key from internal representation to Big-Endian export representation. +The function converts the X,Y coordinates of public key EC point to big endianness, +and sets the public key as follows: +
  • In case "Uncompressed" point: PubKey = PC||X||Y, PC = 0x4 - single byte;
  • +
  • In case of "Hybrid" key PC = 0x6.
  • +
  • In case of "Compressed" key PC = 0x2.
+\note Size of output X and Y coordinates is equal to ModSizeInBytes. +@return CRYS_OK on success. +@return A non-zero value on failure as defined crys_ecpki_error.h. +*/ +CIMPORT_C CRYSError_t CRYS_ECPKI_ExportPublKey( + CRYS_ECPKI_UserPublKey_t *pUserPublKey, /*!< [in] Pointer to the input public key structure (in Little-Endian form). */ + CRYS_ECPKI_PointCompression_t compression, /*!< [in] Compression mode: Compressed, Uncompressed or Hybrid. */ + uint8_t *pExternPublKey, /*!< [out] Pointer to the exported public key array, in compressed or uncompressed + or hybrid form: + [PC||X||Y] Big-Endian representation, structured according to [IEEE1363]. + In compressed form, Y is omitted. */ + uint32_t *pPublKeySizeBytes /*!< [in/out] Pointer used for the input of the user public key buffer size + (in bytes), and the output of the size of the converted public key in bytes. */ + ); + + + +#ifdef __cplusplus +} +#endif +/** +@} + */ +#endif diff --git a/features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_ecpki_dh.h b/features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_ecpki_dh.h new file mode 100644 index 00000000000..b95abe55e74 --- /dev/null +++ b/features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_ecpki_dh.h @@ -0,0 +1,90 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + + +#ifndef CRYS_ECPKI_DH_H +#define CRYS_ECPKI_DH_H + +/*! @file +@brief Defines the API that supports EC Diffie-Hellman shared secret value derivation primitives. +@defgroup crys_ecpki_dh CryptoCell ECC Diffie-Hellman APIs +@{ +@ingroup cryptocell_ecpki +*/ + + +#include "crys_ecpki_types.h" +#include "crys_ecpki_error.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/*********************************************************************** + * CRYS_ECDH_SVDP_DH function * + ***********************************************************************/ +/*! +@brief Creates the shared secret value according to [IEEE1363, ANS X9.63]: + +
  1. Checks input-parameter pointers and EC Domain in public and private +keys.
  2. +
  3. Derives the partner public key and calls the EcWrstDhDeriveSharedSecret +function, which performs EC SVDP operations.
+\note The term "User" +refers to any party that calculates a shared secret value using this primitive. +The term "Partner" refers to any other party of shared secret value calculation. +Partner's public key shall be validated before using in this primitive. + +@return CRYS_OK on success. +@return A non-zero value on failure as defined crys_ecpki_error.h. +*/ +CIMPORT_C CRYSError_t CRYS_ECDH_SVDP_DH( + CRYS_ECPKI_UserPublKey_t *PartnerPublKey_ptr, /*!< [in] Pointer to a partner public key. */ + CRYS_ECPKI_UserPrivKey_t *UserPrivKey_ptr, /*!< [in] Pointer to a user private key. */ + uint8_t *SharedSecretValue_ptr, /*!< [out] Pointer to an output buffer that will contain the shared + secret value. */ + uint32_t *SharedSecrValSize_ptr, /*!< [in/out] Pointer to the size of user-passed buffer (in) and + actual size of output of calculated shared secret value + (out). */ + CRYS_ECDH_TempData_t *TempBuff_ptr /*!< [in] Pointer to a temporary buffer. */); + +#ifdef __cplusplus +} +#endif +/** +@} + */ +#endif diff --git a/features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_ecpki_ecdsa.h b/features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_ecpki_ecdsa.h new file mode 100644 index 00000000000..02db31d9481 --- /dev/null +++ b/features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_ecpki_ecdsa.h @@ -0,0 +1,139 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + + +#ifndef CRYS_ECPKI_ECDSA_H +#define CRYS_ECPKI_ECDSA_H + +/*! +@file +@brief Defines the APIs that support the ECDSA functions. +@defgroup crys_ecpki_ecdsa CryptoCell ECDSA APIs +@{ +@ingroup cryptocell_ecpki +*/ + +#include "crys_error.h" +#include "crys_ecpki_types.h" +#include "crys_hash.h" +#include "crys_rnd.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + + + +/************************************************************************** + * CRYS_ECDSA_Sign - integrated function + **************************************************************************/ +/*! +@brief This function performs an ECDSA sign operation in integrated form. + +\note +Using of HASH functions with HASH size greater than EC modulus size, is not recommended!. +Algorithm according [ANS X9.62] standard. + +The message data may be either a non-hashed data or a digest of a hash function. +For a non-hashed data, the message data will be hashed using the hash function indicated by ::CRYS_ECPKI_HASH_OpMode_t. +For a digest, ::CRYS_ECPKI_HASH_OpMode_t should indicate the hash function that the message data was created by, and it will not be hashed. + +@return CRYS_OK on success. +@return A non-zero value on failure as defined crys_ecpki_error.h, crys_hash_error.h or crys_rnd_error.h. +**/ +CIMPORT_C CRYSError_t CRYS_ECDSA_Sign( + void *rndState_ptr, /*!< [in/out] Pointer to the RND state structure. */ + SaSiRndGenerateVectWorkFunc_t rndGenerateVectFunc, /*!< [in] Pointer to the random vector generation function. */ + CRYS_ECDSA_SignUserContext_t *pSignUserContext, /*!< [in/out] Pointer to the user buffer for signing the database. */ + CRYS_ECPKI_UserPrivKey_t *pSignerPrivKey, /*!< [in] A pointer to a user private key structure. */ + CRYS_ECPKI_HASH_OpMode_t hashMode, /*!< [in] One of the supported SHA-x HASH modes, as defined in + ::CRYS_ECPKI_HASH_OpMode_t. + \note MD5 is not supported. */ + uint8_t *pMessageDataIn, /*!< [in] Pointer to the input data to be signed. + The size of the scatter/gather list representing the data buffer + is limited to 128 entries, and the size of each entry is limited + to 64KB (fragments larger than 64KB are broken into + fragments <= 64KB). */ + uint32_t messageSizeInBytes, /*!< [in] Size of message data in bytes. */ + uint8_t *pSignatureOut, /*!< [in] Pointer to a buffer for output of signature. */ + uint32_t *pSignatureOutSize /*!< [in/out] Pointer to the signature size. Used to pass the size of + the SignatureOut buffer (in), which must be >= 2 + * OrderSizeInBytes. When the API returns, + it is replaced with the size of the actual signature (out). */ + ); + + + +/************************************************************************** + * CRYS_ECDSA_Verify integrated function + **************************************************************************/ +/*! +@brief This function performs an ECDSA verify operation in integrated form. +Algorithm according [ANS X9.62] standard. + +The message data may be either a non-hashed data or a digest of a hash function. +For a non-hashed data, the message data will be hashed using the hash function indicated by ::CRYS_ECPKI_HASH_OpMode_t. +For a digest, ::CRYS_ECPKI_HASH_OpMode_t should indicate the hash function that the message data was created by, and it will not be hashed. + +@return CRYS_OK on success. +@return A non-zero value on failure as defined crys_ecpki_error.h or crys_hash_error.h. +*/ +CIMPORT_C CRYSError_t CRYS_ECDSA_Verify ( + CRYS_ECDSA_VerifyUserContext_t *pVerifyUserContext, /*!< [in] Pointer to the user buffer for signing the database. */ + CRYS_ECPKI_UserPublKey_t *pUserPublKey, /*!< [in] Pointer to a user public key structure. */ + CRYS_ECPKI_HASH_OpMode_t hashMode, /*!< [in] One of the supported SHA-x HASH modes, as defined in + ::CRYS_ECPKI_HASH_OpMode_t. + \note MD5 is not supported. */ + uint8_t *pSignatureIn, /*!< [in] Pointer to the signature to be verified. */ + uint32_t SignatureSizeBytes, /*!< [in] Size of the signature (in bytes). */ + uint8_t *pMessageDataIn, /*!< [in] Pointer to the input data that was signed (same as given to + the signing function). The size of the scatter/gather list representing + the data buffer is limited to 128 entries, and the size of each entry is + limited to 64KB (fragments larger than 64KB are broken into fragments <= 64KB). */ + uint32_t messageSizeInBytes /*!< [in] Size of the input data (in bytes). */ + ); + + +/**********************************************************************************************************/ + + +#ifdef __cplusplus +} +#endif +/** +@} + */ +#endif diff --git a/features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_ecpki_error.h b/features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_ecpki_error.h new file mode 100644 index 00000000000..9eb141dc560 --- /dev/null +++ b/features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_ecpki_error.h @@ -0,0 +1,303 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + + +#ifndef CRYS_ECPKI_ERROR_H +#define CRYS_ECPKI_ERROR_H + + +/*! +@file +@brief This module contains the definitions of the CRYS ECPKI errors. +@defgroup crys_ecpki_error CryptoCell ECC specific errors +@{ +@ingroup cryptocell_ecpki +*/ + +#include "crys_error.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + + +/************************ Defines ******************************/ + +/* CRYS_ECPKI_MODULE_ERROR_BASE = 0x00F00800 */ + +/********************************************************************************************* + * CRYS ECPKI MODULE ERRORS * + *********************************************************************************************/ +/*! Illegal domain ID. */ +#define CRYS_ECPKI_ILLEGAL_DOMAIN_ID_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x1UL) +/*! Illegal domain pointer. */ +#define CRYS_ECPKI_DOMAIN_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x2UL) +/* The CRYS ECPKI GEN KEY PAIR module errors */ +/*! Illegal private key pointer. */ +#define CRYS_ECPKI_GEN_KEY_INVALID_PRIVATE_KEY_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x3UL) +/*! Illegal public key pointer. */ +#define CRYS_ECPKI_GEN_KEY_INVALID_PUBLIC_KEY_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x4UL) +/*! Illegal temporary buffer pointer. */ +#define CRYS_ECPKI_GEN_KEY_INVALID_TEMP_DATA_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x5UL) +/*! Illegal RND context pointer. */ +#define CRYS_ECPKI_RND_CONTEXT_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x6UL) + +/************************************************************************************************************ +* The CRYS ECPKI BUILD KEYS MODULE ERRORS * +*************************************************************************************************************/ +/*! Illegal compression mode. */ +#define CRYS_ECPKI_BUILD_KEY_INVALID_COMPRESSION_MODE_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x07UL) +/*! Illegal domain ID. */ +#define CRYS_ECPKI_BUILD_KEY_ILLEGAL_DOMAIN_ID_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x08UL) +/*! Illegal private key pointer. */ +#define CRYS_ECPKI_BUILD_KEY_INVALID_PRIV_KEY_IN_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x09UL) +/*! Illegal private key structure pointer. */ +#define CRYS_ECPKI_BUILD_KEY_INVALID_USER_PRIV_KEY_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x0AUL) +/*! Illegal private key size. */ +#define CRYS_ECPKI_BUILD_KEY_INVALID_PRIV_KEY_SIZE_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x0BUL) +/*! Illegal private key data. */ +#define CRYS_ECPKI_BUILD_KEY_INVALID_PRIV_KEY_DATA_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x0CUL) +/*! Illegal public key pointer. */ +#define CRYS_ECPKI_BUILD_KEY_INVALID_PUBL_KEY_IN_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x0DUL) +/*! Illegal public key structure pointer. */ +#define CRYS_ECPKI_BUILD_KEY_INVALID_USER_PUBL_KEY_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x0EUL) +/*! Illegal public key size. */ +#define CRYS_ECPKI_BUILD_KEY_INVALID_PUBL_KEY_SIZE_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x0FUL) +/*! Illegal public key data. */ +#define CRYS_ECPKI_BUILD_KEY_INVALID_PUBL_KEY_DATA_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x10UL) +/*! Illegal EC build check mode option. */ +#define CRYS_ECPKI_BUILD_KEY_INVALID_CHECK_MODE_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x11UL) +/*! Illegal temporary buffer pointer. */ +#define CRYS_ECPKI_BUILD_KEY_INVALID_TEMP_BUFF_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x12UL) + +/* The CRYS ECPKI EXPORT PUBLIC KEY MODULE ERRORS */ +/*! Illegal public key structure pointer. */ +#define CRYS_ECPKI_EXPORT_PUBL_KEY_INVALID_USER_PUBL_KEY_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x14UL) +/*! Illegal public key compression mode. */ +#define CRYS_ECPKI_EXPORT_PUBL_KEY_ILLEGAL_COMPRESSION_MODE_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x15UL) +/*! Illegal output public key pointer. */ +#define CRYS_ECPKI_EXPORT_PUBL_KEY_INVALID_EXTERN_PUBL_KEY_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x16UL) +/*! Illegal output public key size pointer. */ +#define CRYS_ECPKI_EXPORT_PUBL_KEY_INVALID_PUBL_KEY_SIZE_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x17UL) +/*! Illegal output public key size. */ +#define CRYS_ECPKI_EXPORT_PUBL_KEY_INVALID_PUBL_KEY_SIZE_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x18UL) +/*! Illegal domain ID. */ +#define CRYS_ECPKI_EXPORT_PUBL_KEY_ILLEGAL_DOMAIN_ID_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x19UL) +/*! Validation of public key failed. */ +#define CRYS_ECPKI_EXPORT_PUBL_KEY_ILLEGAL_VALIDATION_TAG_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x1AUL) +/*! Validation of public key failed. */ +#define CRYS_ECPKI_EXPORT_PUBL_KEY_INVALID_PUBL_KEY_DATA_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x1BUL) + +/* The CRYS ECPKI BUILD ECC DOMAIN ERRORS */ +/*! Illegal domain ID. */ +#define CRYS_ECPKI_BUILD_DOMAIN_ID_IS_NOT_VALID_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x20UL) +/*! Illegal domain ID pointer. */ +#define CRYS_ECPKI_BUILD_DOMAIN_DOMAIN_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x21UL) +/*! Illegal domain parameter pointer. */ +#define CRYS_ECPKI_BUILD_DOMAIN_EC_PARAMETR_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x22UL) +/*! Illegal domain parameter size. */ +#define CRYS_ECPKI_BUILD_DOMAIN_EC_PARAMETR_SIZE_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x23UL) +/*! Illegal domain cofactor parameters. */ +#define CRYS_ECPKI_BUILD_DOMAIN_COFACTOR_PARAMS_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x24UL) +/*! Insufficient strength. */ +#define CRYS_ECPKI_BUILD_DOMAIN_SECURITY_STRENGTH_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x25UL) +/*! SCA resistance error. */ +#define CRYS_ECPKI_BUILD_SCA_RESIST_ILLEGAL_MODE_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x26UL) + + +/*! Internal PKI error */ +#define CRYS_ECPKI_PKI_INTERNAL_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x30UL) + +/************************************************************************************************************ + * CRYS EC DIFFIE-HELLMAN MODULE ERRORS +*************************************************************************************************************/ +/* The CRYS EC SVDP_DH Function errors */ +/*! Illegal partner's public key pointer. */ +#define CRYS_ECDH_SVDP_DH_INVALID_PARTNER_PUBL_KEY_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x31UL) +/*! Partner's public key validation failed. */ +#define CRYS_ECDH_SVDP_DH_PARTNER_PUBL_KEY_VALID_TAG_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x32UL) +/*! Illegal user private key pointer. */ +#define CRYS_ECDH_SVDP_DH_INVALID_USER_PRIV_KEY_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x33UL) +/*! Private key validation failed. */ +#define CRYS_ECDH_SVDP_DH_USER_PRIV_KEY_VALID_TAG_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x34UL) +/*! Illegal shared secret pointer. */ +#define CRYS_ECDH_SVDP_DH_INVALID_SHARED_SECRET_VALUE_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x35UL) +/*! Illegal temporary buffer pointer. */ +#define CRYS_ECDH_SVDP_DH_INVALID_TEMP_DATA_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x36UL) +/*! Illegal shared secret size pointer. */ +#define CRYS_ECDH_SVDP_DH_INVALID_SHARED_SECRET_VALUE_SIZE_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x37UL) +/*! Illegal shared secret size. */ +#define CRYS_ECDH_SVDP_DH_INVALID_SHARED_SECRET_VALUE_SIZE_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x38UL) +/*! Illegal domain ID. */ +#define CRYS_ECDH_SVDP_DH_ILLEGAL_DOMAIN_ID_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x39UL) +/*! Illegal private and public domain ID are different. */ +#define CRYS_ECDH_SVDP_DH_NOT_CONCENT_PUBL_AND_PRIV_DOMAIN_ID_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x3AUL) + + +/************************************************************************************************************ + * CRYS ECDSA MODULE ERRORS + ************************************************************************************************************/ +/* The CRYS ECDSA Signing errors */ +/*! Illegal domain ID. */ +#define CRYS_ECDSA_SIGN_INVALID_DOMAIN_ID_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x50UL) +/*! Illegal context pointer. */ +#define CRYS_ECDSA_SIGN_INVALID_USER_CONTEXT_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x51UL) +/*! Illegal private key pointer. */ +#define CRYS_ECDSA_SIGN_INVALID_USER_PRIV_KEY_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x52UL) +/*! Illegal hash operation mode. */ +#define CRYS_ECDSA_SIGN_ILLEGAL_HASH_OP_MODE_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x53UL) +/*! Illegal data in pointer. */ +#define CRYS_ECDSA_SIGN_INVALID_MESSAGE_DATA_IN_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x54UL) +/*! Illegal data in size. */ +#define CRYS_ECDSA_SIGN_INVALID_MESSAGE_DATA_IN_SIZE_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x55UL) +/*! Context validation failed. */ +#define CRYS_ECDSA_SIGN_USER_CONTEXT_VALIDATION_TAG_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x57UL) +/*! User's private key validation failed. */ +#define CRYS_ECDSA_SIGN_USER_PRIV_KEY_VALIDATION_TAG_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x58UL) +/*! Illegal signature pointer. */ +#define CRYS_ECDSA_SIGN_INVALID_SIGNATURE_OUT_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x60UL) +/*! Illegal signature size pointer. */ +#define CRYS_ECDSA_SIGN_INVALID_SIGNATURE_OUT_SIZE_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x61UL) +/*! Illegal signature size. */ +#define CRYS_ECDSA_SIGN_INVALID_SIGNATURE_OUT_SIZE_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x62UL) +/*! Ephemeral key error. */ +#define CRYS_ECDSA_SIGN_INVALID_IS_EPHEMER_KEY_INTERNAL_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x63UL) +/*! Illegal ephemeral key pointer. */ +#define CRYS_ECDSA_SIGN_INVALID_EPHEMERAL_KEY_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x64UL) +/*! Illegal RND context pointer. */ +#define CRYS_ECDSA_SIGN_INVALID_RND_CONTEXT_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x65UL) +/*! Illegal RND function pointer. */ +#define CRYS_ECDSA_SIGN_INVALID_RND_FUNCTION_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x66UL) +/*! Signature calculation failed. */ +#define CRYS_ECDSA_SIGN_SIGNING_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x67UL) + +/* The CRYS ECDSA Verifying errors */ +/*! Illegal domain ID. */ +#define CRYS_ECDSA_VERIFY_INVALID_DOMAIN_ID_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x70UL) +/*! Illegal user's context pointer. */ +#define CRYS_ECDSA_VERIFY_INVALID_USER_CONTEXT_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x71UL) +/*! Illegal public key pointer. */ +#define CRYS_ECDSA_VERIFY_INVALID_SIGNER_PUBL_KEY_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x72UL) +/*! Illegal hash operation mode. */ +#define CRYS_ECDSA_VERIFY_ILLEGAL_HASH_OP_MODE_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x73UL) +/*! Illegal signature pointer. */ +#define CRYS_ECDSA_VERIFY_INVALID_SIGNATURE_IN_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x76UL) +/*! Illegal signature size. */ +#define CRYS_ECDSA_VERIFY_INVALID_SIGNATURE_SIZE_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x77UL) +/*! Illegal data in pointer. */ +#define CRYS_ECDSA_VERIFY_INVALID_MESSAGE_DATA_IN_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x80UL) +/*! Illegal data in size. */ +#define CRYS_ECDSA_VERIFY_INVALID_MESSAGE_DATA_IN_SIZE_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x81UL) +/*! Context validation failed. */ +#define CRYS_ECDSA_VERIFY_USER_CONTEXT_VALIDATION_TAG_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x82UL) +/*! public key validation failed. */ +#define CRYS_ECDSA_VERIFY_SIGNER_PUBL_KEY_VALIDATION_TAG_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x83UL) +/*! Verification failed. */ +#define CRYS_ECDSA_VERIFY_INCONSISTENT_VERIFY_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x84UL) + +/*! Illegal parameters. */ +#define CRYS_ECC_ILLEGAL_PARAMS_ACCORDING_TO_PRIV_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0xD3UL) +/*! Illegal hash mode. */ +#define CRYS_ECC_ILLEGAL_HASH_MODE_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0xE0UL) + + +/************************************************************************************************************ + * CRYS ECPKI MODULE COMMON ERRORS +*************************************************************************************************************/ +/*! Illegal RND function pointer. */ +#define CRYS_ECPKI_INVALID_RND_FUNC_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x90UL) +/*! Illegal RND context pointer. */ +#define CRYS_ECPKI_INVALID_RND_CTX_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x91UL) +/*! Illegal domain ID. */ +#define CRYS_ECPKI_INVALID_DOMAIN_ID_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x92UL) +/*! Private key validation failed. */ +#define CRYS_ECPKI_INVALID_PRIV_KEY_TAG_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x93UL) +/*! Public key validation failed. */ +#define CRYS_ECPKI_INVALID_PUBL_KEY_TAG_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x94UL) +/*! Illegal data in. */ +#define CRYS_ECPKI_INVALID_DATA_IN_PASSED_STRUCT_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0x95UL) + +/************************************************************************************************************ + * CRYS ECIES MODULE ERRORS +*************************************************************************************************************/ +/*! Illegal public key pointer. */ +#define CRYS_ECIES_INVALID_PUBL_KEY_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0xE0UL) +/*! Public key validation failed. */ +#define CRYS_ECIES_INVALID_PUBL_KEY_TAG_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0xE1UL) +/*! Illegal private key pointer. */ +#define CRYS_ECIES_INVALID_PRIV_KEY_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0xE2UL) +/*! Private key validation failed. */ +#define CRYS_ECIES_INVALID_PRIV_KEY_TAG_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0xE3UL) +/*! Illegal private key value. */ +#define CRYS_ECIES_INVALID_PRIV_KEY_VALUE_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0xE4UL) +/*! Illegal KDF derivation mode. */ +#define CRYS_ECIES_INVALID_KDF_DERIV_MODE_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0xE5UL) +/*! Illegal KDF hash mode. */ +#define CRYS_ECIES_INVALID_KDF_HASH_MODE_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0xE6UL) +/*! Illegal secret key pointer. */ +#define CRYS_ECIES_INVALID_SECRET_KEY_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0xE7UL) +/*! Illegal secret key size. */ +#define CRYS_ECIES_INVALID_SECRET_KEY_SIZE_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0xE8UL) +/*! Illegal cipher data pointer. */ +#define CRYS_ECIES_INVALID_CIPHER_DATA_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0xE9UL) +/*! Illegal cipher data size pointer. */ +#define CRYS_ECIES_INVALID_CIPHER_DATA_SIZE_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0xEAUL) +/*! Illegal cipher data size. */ +#define CRYS_ECIES_INVALID_CIPHER_DATA_SIZE_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0xEBUL) +/*! Illegal temporary buffer pointer. */ +#define CRYS_ECIES_INVALID_TEMP_DATA_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0xECUL) +/*! Illegal ephemeral key pointer */ +#define CRYS_ECIES_INVALID_EPHEM_KEY_PAIR_PTR_ERROR (CRYS_ECPKI_MODULE_ERROR_BASE + 0xEDUL) + +/************************ Enums ********************************/ + +/************************ Typedefs ****************************/ + +/************************ Structs ******************************/ + +/************************ Public Variables **********************/ + +/************************ Public Functions **********************/ + +#ifdef __cplusplus +} +#endif +/** +@} + */ +#endif + + diff --git a/features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_ecpki_kg.h b/features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_ecpki_kg.h new file mode 100644 index 00000000000..10fcd49ab36 --- /dev/null +++ b/features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_ecpki_kg.h @@ -0,0 +1,88 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + + +#ifndef CRYS_ECPKI_KG_H +#define CRYS_ECPKI_KG_H + +/*! @file +@brief Defines the API for generation of ECC private and public keys. +@defgroup crys_ecpki_kg CryptoCell ECC Key Generation APIs +@{ +@ingroup cryptocell_ecpki +*/ + + +#include "crys_error.h" +#include "crys_rnd.h" +#include "crys_ecpki_types.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/***************** CRYS_ECPKI_GenKeyPair function **********************/ +/*! +@brief Generates a pair of private and public keys in internal representation according to [ANS X9.62]. + +@return CRYS_OK on success. +@return A non-zero value on failure as defined crys_ecpki_error.h or crys_rnd_error.h +*/ +CIMPORT_C CRYSError_t CRYS_ECPKI_GenKeyPair( + void *rndState_ptr, /*!< [in/out] Pointer to the RND state structure. */ + SaSiRndGenerateVectWorkFunc_t rndGenerateVectFunc, /*!< [in] Pointer to the random vector generation function. */ + const CRYS_ECPKI_Domain_t *pDomain, /*!< [in] Pointer to EC domain (curve). */ + CRYS_ECPKI_UserPrivKey_t *pUserPrivKey, /*!< [out] Pointer to the private key structure. This structure is used as input to the + ECPKI cryptographic primitives. */ + CRYS_ECPKI_UserPublKey_t *pUserPublKey, /*!< [out] Pointer to the public key structure. This structure is used as input to the + ECPKI cryptographic primitives. */ + CRYS_ECPKI_KG_TempData_t *pTempData, /*!< [in] Temporary buffers for internal use, defined in ::CRYS_ECPKI_KG_TempData_t. */ + CRYS_ECPKI_KG_FipsContext_t *pFipsCtx /*!< [in] Pointer to temporary buffer used in case FIPS certification if required. */ +); + + + +#ifdef __cplusplus +} +#endif +/** +@} + */ +#endif + + + + diff --git a/features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_ecpki_types.h b/features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_ecpki_types.h new file mode 100644 index 00000000000..2b4ee2c6464 --- /dev/null +++ b/features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_ecpki_types.h @@ -0,0 +1,478 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + + +#ifndef CRYS_ECPKI_TYPES_H +#define CRYS_ECPKI_TYPES_H + +/*! +@file +@brief Contains all of the enums and definitions that are used for the CRYS ECPKI APIs. +@defgroup crys_ecpki_types CryptoCell ECC specific types +@{ +@ingroup cryptocell_ecpki +*/ + +#include "ssi_pal_types_plat.h" +#include "crys_hash.h" +#include "crys_pka_defs_hw.h" +#include "ssi_pal_compiler.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + + +/************************ Defines ******************************/ +/*! Internal buffer size in words. */ +#define CRYS_PKA_DOMAIN_LLF_BUFF_SIZE_IN_WORDS (10 + 3*CRYS_ECPKI_MODUL_MAX_LENGTH_IN_WORDS) + +/************************************************************************************** + * Enumerators + ***************************************************************************************/ + +/*------------------------------------------------------------------*/ +/*! Enumerator for the EC Domain idetifier + References: [13] - SEC 2: Recommended elliptic curve domain parameters. + Version 1.0. Certicom 2000. + [8] - WAP-261-WTLS-20010406-a, Version 06-April-2001. */ + +typedef enum +{ + /* For prime field */ + CRYS_ECPKI_DomainID_secp160k1, /*!< EC secp160r1 */ + CRYS_ECPKI_DomainID_secp160r1, /*!< EC secp160k1 */ + CRYS_ECPKI_DomainID_secp160r2, /*!< EC secp160r2 */ + CRYS_ECPKI_DomainID_secp192k1, /*!< EC secp192k1 */ + CRYS_ECPKI_DomainID_secp192r1, /*!< EC secp192r1 */ + CRYS_ECPKI_DomainID_secp224k1, /*!< EC secp224k1 */ + CRYS_ECPKI_DomainID_secp224r1, /*!< EC secp224r1 */ + CRYS_ECPKI_DomainID_secp256k1, /*!< EC secp256k1 */ + CRYS_ECPKI_DomainID_secp256r1, /*!< EC secp256r1 */ + CRYS_ECPKI_DomainID_secp384r1, /*!< EC secp384r1 */ + CRYS_ECPKI_DomainID_secp521r1, /*!< EC secp521r1 */ + + CRYS_ECPKI_DomainID_Builded, /*!< User given, not identified. */ + CRYS_ECPKI_DomainID_OffMode, /*!< Reserved.*/ + + CRYS_ECPKI_DomainIDLast = 0x7FFFFFFF, /*! Reserved.*/ + +}CRYS_ECPKI_DomainID_t; + + +/*------------------------------------------------------------------*/ +/*! Defines the enum for the HASH operation mode. + * The enumerator defines 6 HASH modes according to IEEE 1363. + * + */ +typedef enum +{ + CRYS_ECPKI_HASH_SHA1_mode = 0, /*!< The message data will be hashed with SHA1. */ + CRYS_ECPKI_HASH_SHA224_mode = 1, /*!< The message data will be hashed with SHA224. */ + CRYS_ECPKI_HASH_SHA256_mode = 2, /*!< The message data will be hashed with SHA256. */ + CRYS_ECPKI_HASH_SHA384_mode = 3, /*!< The message data will be hashed with SHA384. */ + CRYS_ECPKI_HASH_SHA512_mode = 4, /*!< The message data will be hashed with SHA512. */ + + CRYS_ECPKI_AFTER_HASH_SHA1_mode = 5, /*!< The message data is a digest of SHA1 and will not be hashed. */ + CRYS_ECPKI_AFTER_HASH_SHA224_mode = 6, /*!< The message data is a digest of SHA224 and will not be hashed. */ + CRYS_ECPKI_AFTER_HASH_SHA256_mode = 7, /*!< The message data is a digest of SHA256 and will not be hashed. */ + CRYS_ECPKI_AFTER_HASH_SHA384_mode = 8, /*!< The message data is a digest of SHA384 and will not be hashed. */ + CRYS_ECPKI_AFTER_HASH_SHA512_mode = 9, /*!< The message data is a digest of SHA512 and will not be hashed. */ + + + CRYS_ECPKI_HASH_NumOfModes, /*!< Maximal number of HASH modes. */ + CRYS_ECPKI_HASH_OpModeLast = 0x7FFFFFFF, /*!< Reserved. */ + +}CRYS_ECPKI_HASH_OpMode_t; + + +/*---------------------------------------------------*/ +/*! Enumerator for the EC point compression idetifier. */ +typedef enum +{ + CRYS_EC_PointCompressed = 2, /*!< Compressed point. */ + CRYS_EC_PointUncompressed = 4, /*!< Uncompressed point. */ + CRYS_EC_PointContWrong = 5, /*!< Wrong Point Control value. */ + CRYS_EC_PointHybrid = 6, /*!< Hybrid point. */ + + CRYS_EC_PointCompresOffMode = 8, /*!< Reserved. */ + + CRYS_ECPKI_PointCompressionLast= 0x7FFFFFFF, /*!< Reserved. */ + +}CRYS_ECPKI_PointCompression_t; + + +/*! EC key checks defintions. */ +typedef enum { + CheckPointersAndSizesOnly = 0, /*!< Only preliminary input parameters are checked. */ + ECpublKeyPartlyCheck = 1, /*!< Preliminary input parameters check and verify that EC PubKey point is on the curve. */ + ECpublKeyFullCheck = 2, /*!< All the above and in addition verifies that EC_GeneratorOrder*PubKey = O */ + + PublKeyChecingOffMode, /*! Reserved. */ + EC_PublKeyCheckModeLast = 0x7FFFFFFF, /*! Reserved. */ +}EC_PublKeyCheckMode_t; + +/*----------------------------------------------------*/ +/*! Defintion of sw SCA protection. */ +typedef enum { + SCAP_Inactive, /*! Inactive.*/ + SCAP_Active, /*! Active.*/ + SCAP_OFF_MODE, /*! Reserved. */ + SCAP_LAST = 0x7FFFFFFF /*! Reserved. */ +} CRYS_ECPKI_ScaProtection_t; + + +/************************************************************************************** + * EC Domain structure definition + ***************************************************************************************/ + +/*! The structure containing the EC domain parameters in little-endian form + EC equation: Y^2 = X^3 + A*X + B over prime fild GFp. */ +typedef struct { + + /*! EC modulus: P. */ + uint32_t ecP [CRYS_ECPKI_MODUL_MAX_LENGTH_IN_WORDS]; + /*! EC equation parameter a. */ + uint32_t ecA [CRYS_ECPKI_MODUL_MAX_LENGTH_IN_WORDS]; + /*! EC equation parameter b. */ + uint32_t ecB [CRYS_ECPKI_MODUL_MAX_LENGTH_IN_WORDS]; + /*! Order of generator. */ + uint32_t ecR [CRYS_ECPKI_MODUL_MAX_LENGTH_IN_WORDS + 1]; + /*! EC cofactor EC_Cofactor_K + Generator (EC base point) coordinates in projective form. */ + uint32_t ecGx [CRYS_ECPKI_MODUL_MAX_LENGTH_IN_WORDS]; + /*! EC cofactor EC_Cofactor_K + Generator (EC base point) coordinates in projective form. */ + uint32_t ecGy [CRYS_ECPKI_MODUL_MAX_LENGTH_IN_WORDS]; + /*! EC cofactor EC_Cofactor_K + Generator (EC base point) coordinates in projective form. */ + uint32_t ecH; + /*! Specific fields that are used by the low level.*/ + uint32_t llfBuff[CRYS_PKA_DOMAIN_LLF_BUFF_SIZE_IN_WORDS]; + /*! Size of fields in bits. */ + uint32_t modSizeInBits; + /*! Order size in bits. */ + uint32_t ordSizeInBits; + /*! Size of each inserted Barret tag in words; 0 - if not inserted.*/ + uint32_t barrTagSizeInWords; + /*! EC Domain identifier.*/ + CRYS_ECPKI_DomainID_t DomainID; + + /*! Internal buffer. */ + int8_t name[20]; + +} CRYS_ECPKI_Domain_t; + + + +/************************************************************************************** + * EC point structures definitions + ***************************************************************************************/ + +/*! The structure containing the EC point in affine coordinates + and little endian form. */ +typedef struct +{ + /*! Point coordinate X. */ + uint32_t x[CRYS_ECPKI_MODUL_MAX_LENGTH_IN_WORDS]; + /*! Point coordinate Y. */ + uint32_t y[CRYS_ECPKI_MODUL_MAX_LENGTH_IN_WORDS]; + +}CRYS_ECPKI_PointAffine_t; + + +/************************************************************************************** + * ECPKI public and private key Structures + ***************************************************************************************/ + +/* --------------------------------------------------------------------- */ +/* .................. The public key structures definitions ............ */ +/* --------------------------------------------------------------------- */ + +/*! The structure containing the Public Key in affine coordinates.*/ +typedef struct +{ + /*! Public Key coordinate X.*/ + uint32_t x[CRYS_ECPKI_MODUL_MAX_LENGTH_IN_WORDS]; + /*! Public Key coordinate Y.*/ + uint32_t y[CRYS_ECPKI_MODUL_MAX_LENGTH_IN_WORDS]; + /*! EC Domain.*/ + CRYS_ECPKI_Domain_t domain; + /*! Point type.*/ + uint32_t pointType; +} CRYS_ECPKI_PublKey_t; + +/*! The EC public key's user structure prototype. This structure must be saved by the user, and is used as input to the ECC functions +(such as ::CRYS_ECDSA_Verify etc.). */ +typedef struct CRYS_ECPKI_UserPublKey_t +{ + /*! Validation tag.*/ + uint32_t valid_tag; + /*! Public key data. */ + uint32_t PublKeyDbBuff[(sizeof(CRYS_ECPKI_PublKey_t)+3)/4]; + +} CRYS_ECPKI_UserPublKey_t; + + +/* --------------------------------------------------------------------- */ +/* .................. The private key structures definitions ........... */ +/* --------------------------------------------------------------------- */ + +/*! Structure containing the Private key data. */ +typedef struct +{ + /*! Private Key data. */ + uint32_t PrivKey[CRYS_ECPKI_MODUL_MAX_LENGTH_IN_WORDS + 1]; + /*! Domain. */ + CRYS_ECPKI_Domain_t domain; + /*! SCA protection mode. */ + CRYS_ECPKI_ScaProtection_t scaProtection; + +}CRYS_ECPKI_PrivKey_t; + + +/*! The EC private key's user structure prototype. This structure must be saved by the user, and is used as input to the ECC functions +(such as ::CRYS_ECDSA_Sign etc.). */ +typedef struct CRYS_ECPKI_UserPrivKey_t +{ + /*! Validation tag. */ + uint32_t valid_tag; + /*! Private key data. */ + uint32_t PrivKeyDbBuff[(sizeof(CRYS_ECPKI_PrivKey_t)+3)/4]; + +} CRYS_ECPKI_UserPrivKey_t; + +/*! ECDH temporary data type */ +typedef struct CRYS_ECDH_TempData_t +{ + /*! Temporary buffers. */ + uint32_t crysEcdhIntBuff[CRYS_PKA_ECDH_BUFF_MAX_LENGTH_IN_WORDS]; +}CRYS_ECDH_TempData_t; + +/*! EC build temporary data. */ +typedef struct CRYS_ECPKI_BUILD_TempData_t +{ + /*! Temporary buffers. */ + uint32_t crysBuildTmpIntBuff[CRYS_PKA_ECPKI_BUILD_TMP_BUFF_MAX_LENGTH_IN_WORDS]; +}CRYS_ECPKI_BUILD_TempData_t; + + + +/************************************************************************** + * CRYS ECDSA context structures + **************************************************************************/ + +/* --------------------------------------------------------------------- */ +/* CRYS ECDSA Signing context structure */ +/* --------------------------------------------------------------------- */ +/*! Internal buffer used in the signing process. */ +typedef uint32_t CRYS_ECDSA_SignIntBuff[CRYS_PKA_ECDSA_SIGN_BUFF_MAX_LENGTH_IN_WORDS]; + +/*! Context definition for Signing operation. */ +typedef struct +{ + /*! Private Key data. */ + CRYS_ECPKI_UserPrivKey_t ECDSA_SignerPrivKey; + + /*! HASH context. */ + CRYS_HASHUserContext_t hashUserCtxBuff; + /*! HASH result buffer. */ + CRYS_HASH_Result_t hashResult; + /*! HASH result size in words. */ + uint32_t hashResultSizeWords; + /*! HASH mode. */ + CRYS_ECPKI_HASH_OpMode_t hashMode; + /*! Internal buffer. */ + CRYS_ECDSA_SignIntBuff crysEcdsaSignIntBuff; +}ECDSA_SignContext_t; + + +/* --------------------------------------------------------------------- */ +/* CRYS ECDSA Signing User context database */ +/* --------------------------------------------------------------------- */ + +/*! User's context definition for signing operation. The context saves the state of the operation and must be saved by the user + till the end of the APIs flow */ +typedef struct CRYS_ECDSA_SignUserContext_t +{ + /*! Signing process data. */ + uint32_t context_buff [(sizeof(ECDSA_SignContext_t)+3)/4]; + /*! Validation tag*/ + uint32_t valid_tag; +} CRYS_ECDSA_SignUserContext_t; + + + +/****************************************************************************/ + +/* --------------------------------------------------------------------- */ +/* CRYS ECDSA Verifying context structure */ +/* --------------------------------------------------------------------- */ +/*! Internal buffer used in the verification process. */ +typedef uint32_t CRYS_ECDSA_VerifyIntBuff[CRYS_PKA_ECDSA_VERIFY_BUFF_MAX_LENGTH_IN_WORDS]; + +/*! Context definition for verification operation. */ +typedef struct +{ + /*! Public key data. */ + CRYS_ECPKI_UserPublKey_t ECDSA_SignerPublKey; + + /*! HASH context. */ + CRYS_HASHUserContext_t hashUserCtxBuff; + /*! HASH result. */ + CRYS_HASH_Result_t hashResult; + /*! HASH result size in words. */ + uint32_t hashResultSizeWords; + /*! HASH mode. */ + CRYS_ECPKI_HASH_OpMode_t hashMode; + /*! Internal buffer. */ + CRYS_ECDSA_VerifyIntBuff crysEcdsaVerIntBuff; + +}ECDSA_VerifyContext_t; + + +/* --------------------------------------------------------------------- */ +/* CRYS ECDSA Verifying User context database */ +/* --------------------------------------------------------------------- */ +/*! User's context definition for verification operation. The context saves the state of the operation and must be saved by the user + till the end of the APIs flow */ +typedef struct CRYS_ECDSA_VerifyUserContext_t +{ + /*! Verification process data. */ + uint32_t context_buff[(sizeof(ECDSA_VerifyContext_t)+3)/4]; + /*! Validation tag. */ + uint32_t valid_tag; +}CRYS_ECDSA_VerifyUserContext_t; + + + + +/* --------------------------------------------------------------------- */ +/* .................. key generation temp buffer ........... */ +/* --------------------------------------------------------------------- */ + +/*! ECPKI KG temporary data type */ +typedef struct CRYS_ECPKI_KG_TempData_t +{ + /*! Internal buffer. */ + uint32_t crysKGIntBuff[CRYS_PKA_KG_BUFF_MAX_LENGTH_IN_WORDS]; +}CRYS_ECPKI_KG_TempData_t; + +/*! ECIES temporary data definition. */ +typedef struct CRYS_ECIES_TempData_t { + + /*! Private key data. */ + CRYS_ECPKI_UserPrivKey_t PrivKey; + /*! Public key data. */ + CRYS_ECPKI_UserPublKey_t PublKey; + /*! Internal buffer. */ + uint32_t zz[3*CRYS_ECPKI_MODUL_MAX_LENGTH_IN_WORDS + 1]; + /*! Internal buffers. */ + union { + CRYS_ECPKI_BUILD_TempData_t buildTempbuff; + CRYS_ECPKI_KG_TempData_t KgTempBuff; + CRYS_ECDH_TempData_t DhTempBuff; + } tmp; + +}CRYS_ECIES_TempData_t; + + +/* --------------------------------------------------------------------- */ +/* .................. defines for FIPS ........... */ +/* --------------------------------------------------------------------- */ + +/*! Order length for the FIPS ECC tests. */ +#define CRYS_ECPKI_FIPS_ORDER_LENGTH (256/SASI_BITS_IN_BYTE) // the order of secp256r1 in bytes + +/*! Context definition required for internal FIPS verification for ECPKI key generation. */ +typedef struct CRYS_ECPKI_KG_FipsContext_t +{ + /*! Signing and verification data. */ + union { + CRYS_ECDSA_SignUserContext_t signCtx; + CRYS_ECDSA_VerifyUserContext_t verifyCtx; + }operationCtx; + /*! Internal buffer. */ + uint32_t signBuff[2*CRYS_ECPKI_ORDER_MAX_LENGTH_IN_WORDS]; +}CRYS_ECPKI_KG_FipsContext_t; + + + +/*! Context defintion, required for internal FIPS verification for ECDSA KAT. * +* The ECDSA KAT tests defined for domain 256r1. */ +typedef struct CRYS_ECDSAFipsKatContext_t{ + /*! Key data. */ + union { + /*! Private key data. */ + struct { + CRYS_ECPKI_UserPrivKey_t PrivKey; + CRYS_ECDSA_SignUserContext_t signCtx; + }userSignData; + /*! Public key data. */ + struct { + CRYS_ECPKI_UserPublKey_t PublKey; + union { + CRYS_ECDSA_VerifyUserContext_t verifyCtx; + CRYS_ECPKI_BUILD_TempData_t tempData; + }buildOrVerify; + }userVerifyData; + }keyContextData; + /*! Internal buffer. */ + uint8_t signBuff[2*CRYS_ECPKI_FIPS_ORDER_LENGTH]; +}CRYS_ECDSAFipsKatContext_t; + +/*! Context definition, required for internal FIPS verification for ECDH KAT. */ +typedef struct CRYS_ECDHFipsKatContext_t{ + /*! Public key data. */ + CRYS_ECPKI_UserPublKey_t pubKey; + /*! Private key data. */ + CRYS_ECPKI_UserPrivKey_t privKey; + /*! Internal buffers. */ + union { + CRYS_ECPKI_BUILD_TempData_t ecpkiTempData; + CRYS_ECDH_TempData_t ecdhTempBuff; + }tmpData; + /*! Buffer for the secret key. */ + uint8_t secretBuff[CRYS_ECPKI_FIPS_ORDER_LENGTH]; +}CRYS_ECDHFipsKatContext_t; + +#ifdef __cplusplus +} +#endif +/** +@} + */ +#endif diff --git a/features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_error.h b/features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_error.h new file mode 100644 index 00000000000..ae9125e7a98 --- /dev/null +++ b/features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_error.h @@ -0,0 +1,273 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + +#ifndef CRYS_ERROR_H +#define CRYS_ERROR_H + +#include "ssi_pal_types.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/*! @file +@brief This module defines the error return code types and the numbering spaces of the error codes +for each module of the layers listed below. +@defgroup crys_error CryptoCell general base error codes +@{ +@ingroup cryptocell_api +*/ + +/*! The definitions of the error number space used for the different modules */ + +/* ........... Error base numeric mapping definitions ................... */ +/* ----------------------------------------------------------------------- */ + + /*! CRYS error base number. */ +#define CRYS_ERROR_BASE 0x00F00000UL + +/*! Error range number assigned for each layer. */ +#define CRYS_ERROR_LAYER_RANGE 0x00010000UL + +/*! Error range number assigned to each module on its specified layer. */ +#define CRYS_ERROR_MODULE_RANGE 0x00000100UL + +/* Defines the layer index for the error mapping. */ +/*! CRYS error layer index. */ +#define CRYS_LAYER_ERROR_IDX 0x00UL +/*! Low level functions error layer index. */ +#define LLF_LAYER_ERROR_IDX 0x01UL +/*! Generic error layer index. */ +#define GENERIC_ERROR_IDX 0x05UL + +/* Defines the module index for error mapping */ +/*! AES error index.*/ +#define AES_ERROR_IDX 0x00UL +/*! DES error index.*/ +#define DES_ERROR_IDX 0x01UL +/*! HASH error index.*/ +#define HASH_ERROR_IDX 0x02UL +/*! HMAC error index.*/ +#define HMAC_ERROR_IDX 0x03UL +/*! RSA error index.*/ +#define RSA_ERROR_IDX 0x04UL +/*! DH error index.*/ +#define DH_ERROR_IDX 0x05UL + +/*! ECPKI error index.*/ +#define ECPKI_ERROR_IDX 0x08UL +/*! RND error index.*/ +#define RND_ERROR_IDX 0x0CUL +/*! Common error index.*/ +#define COMMON_ERROR_IDX 0x0DUL +/*! KDF error index.*/ +#define KDF_ERROR_IDX 0x11UL +/*! HKDF error index.*/ +#define HKDF_ERROR_IDX 0x12UL +/*! AESCCM error index.*/ +#define AESCCM_ERROR_IDX 0x15UL +/*! FIPS error index.*/ +#define FIPS_ERROR_IDX 0x17UL + +/*! PKA error index.*/ +#define PKA_MODULE_ERROR_IDX 0x21UL +/*! CHACHA error index.*/ +#define CHACHA_ERROR_IDX 0x22UL +/*! EC montgomery and edwards error index.*/ +#define EC_MONT_EDW_ERROR_IDX 0x23UL +/*! CHACHA POLY error index.*/ +#define CHACHA_POLY_ERROR_IDX 0x24UL +/*! POLY error index.*/ +#define POLY_ERROR_IDX 0x25UL +/*! SRP error index.*/ +#define SRP_ERROR_IDX 0x26UL + + + +/* .......... defining the error spaces for each module on each layer ........... */ +/* ------------------------------------------------------------------------------ */ + +/*! AES module error base address - 0x00F00000. */ +#define CRYS_AES_MODULE_ERROR_BASE (CRYS_ERROR_BASE + \ + (CRYS_ERROR_LAYER_RANGE * CRYS_LAYER_ERROR_IDX) + \ + (CRYS_ERROR_MODULE_RANGE * AES_ERROR_IDX ) ) + +/*! DES module error base address - 0x00F00100. */ +#define CRYS_DES_MODULE_ERROR_BASE (CRYS_ERROR_BASE + \ + (CRYS_ERROR_LAYER_RANGE * CRYS_LAYER_ERROR_IDX) + \ + (CRYS_ERROR_MODULE_RANGE * DES_ERROR_IDX ) ) + +/*! HASH module error base address - 0x00F00200. */ +#define CRYS_HASH_MODULE_ERROR_BASE (CRYS_ERROR_BASE + \ + (CRYS_ERROR_LAYER_RANGE * CRYS_LAYER_ERROR_IDX) + \ + (CRYS_ERROR_MODULE_RANGE * HASH_ERROR_IDX ) ) + +/*! HMAC module error base address - 0x00F00300. */ +#define CRYS_HMAC_MODULE_ERROR_BASE (CRYS_ERROR_BASE + \ + (CRYS_ERROR_LAYER_RANGE * CRYS_LAYER_ERROR_IDX) + \ + (CRYS_ERROR_MODULE_RANGE * HMAC_ERROR_IDX ) ) + +/*! RSA module error base address - 0x00F00400. */ +#define CRYS_RSA_MODULE_ERROR_BASE (CRYS_ERROR_BASE + \ + (CRYS_ERROR_LAYER_RANGE * CRYS_LAYER_ERROR_IDX) + \ + (CRYS_ERROR_MODULE_RANGE * RSA_ERROR_IDX ) ) + +/*! DH module error base address - 0x00F00500. */ +#define CRYS_DH_MODULE_ERROR_BASE (CRYS_ERROR_BASE + \ + (CRYS_ERROR_LAYER_RANGE * CRYS_LAYER_ERROR_IDX) + \ + (CRYS_ERROR_MODULE_RANGE * DH_ERROR_IDX ) ) + +/*! ECPKI module error base address - 0x00F00800. */ +#define CRYS_ECPKI_MODULE_ERROR_BASE (CRYS_ERROR_BASE + \ + (CRYS_ERROR_LAYER_RANGE * CRYS_LAYER_ERROR_IDX) + \ + (CRYS_ERROR_MODULE_RANGE * ECPKI_ERROR_IDX ) ) + +/*! Low level ECPKI module error base address - 0x00F10800. */ +#define LLF_ECPKI_MODULE_ERROR_BASE (CRYS_ERROR_BASE + \ + (CRYS_ERROR_LAYER_RANGE * LLF_LAYER_ERROR_IDX) + \ + (CRYS_ERROR_MODULE_RANGE * ECPKI_ERROR_IDX ) ) + +/*! RND module error base address - 0x00F00C00. */ +#define CRYS_RND_MODULE_ERROR_BASE (CRYS_ERROR_BASE + \ + (CRYS_ERROR_LAYER_RANGE * CRYS_LAYER_ERROR_IDX) + \ + (CRYS_ERROR_MODULE_RANGE * RND_ERROR_IDX ) ) + +/*! Low level RND module error base address - 0x00F10C00. */ +#define LLF_RND_MODULE_ERROR_BASE (CRYS_ERROR_BASE + \ + (CRYS_ERROR_LAYER_RANGE * LLF_LAYER_ERROR_IDX) + \ + (CRYS_ERROR_MODULE_RANGE * RND_ERROR_IDX ) ) + +/*! COMMMON module error base address - 0x00F00D00. */ +#define CRYS_COMMON_MODULE_ERROR_BASE (CRYS_ERROR_BASE + \ + (CRYS_ERROR_LAYER_RANGE * CRYS_LAYER_ERROR_IDX) + \ + (CRYS_ERROR_MODULE_RANGE * COMMON_ERROR_IDX ) ) + +/*! KDF module error base address - 0x00F01100. */ +#define CRYS_KDF_MODULE_ERROR_BASE (CRYS_ERROR_BASE + \ + (CRYS_ERROR_LAYER_RANGE * CRYS_LAYER_ERROR_IDX) + \ + (CRYS_ERROR_MODULE_RANGE * KDF_ERROR_IDX ) ) + +/*! HKDF module error base address - 0x00F01100. */ +#define CRYS_HKDF_MODULE_ERROR_BASE (CRYS_ERROR_BASE + \ + (CRYS_ERROR_LAYER_RANGE * CRYS_LAYER_ERROR_IDX) + \ + (CRYS_ERROR_MODULE_RANGE * HKDF_ERROR_IDX ) ) + +/*! AESCCM module error base address - 0x00F01500. */ +#define CRYS_AESCCM_MODULE_ERROR_BASE (CRYS_ERROR_BASE + \ + (CRYS_ERROR_LAYER_RANGE * CRYS_LAYER_ERROR_IDX) + \ + (CRYS_ERROR_MODULE_RANGE * AESCCM_ERROR_IDX ) ) + +/*! FIPS module error base address - 0x00F01700. */ +#define CRYS_FIPS_MODULE_ERROR_BASE (CRYS_ERROR_BASE + \ + (CRYS_ERROR_LAYER_RANGE * CRYS_LAYER_ERROR_IDX) + \ + (CRYS_ERROR_MODULE_RANGE * FIPS_ERROR_IDX ) ) + +/*! PKA module error base address - 0x00F02100. */ +#define PKA_MODULE_ERROR_BASE (CRYS_ERROR_BASE + \ + (CRYS_ERROR_LAYER_RANGE * CRYS_LAYER_ERROR_IDX) + \ + (CRYS_ERROR_MODULE_RANGE * PKA_MODULE_ERROR_IDX ) ) + +/*! CHACHA module error base address - 0x00F02200. */ +#define CRYS_CHACHA_MODULE_ERROR_BASE (CRYS_ERROR_BASE + \ + (CRYS_ERROR_LAYER_RANGE * CRYS_LAYER_ERROR_IDX) + \ + (CRYS_ERROR_MODULE_RANGE * CHACHA_ERROR_IDX ) ) +/*! CHACHA POLY module error base address - 0x00F02400. */ +#define CRYS_CHACHA_POLY_MODULE_ERROR_BASE (CRYS_ERROR_BASE + \ + (CRYS_ERROR_LAYER_RANGE * CRYS_LAYER_ERROR_IDX) + \ + (CRYS_ERROR_MODULE_RANGE * CHACHA_POLY_ERROR_IDX ) ) +/*! POLY module error base address - 0x00F02500. */ +#define CRYS_POLY_MODULE_ERROR_BASE (CRYS_ERROR_BASE + \ + (CRYS_ERROR_LAYER_RANGE * CRYS_LAYER_ERROR_IDX) + \ + (CRYS_ERROR_MODULE_RANGE * POLY_ERROR_IDX ) ) + +/*! SRP module error base address - 0x00F02600. */ +#define CRYS_SRP_MODULE_ERROR_BASE (CRYS_ERROR_BASE + \ + (CRYS_ERROR_LAYER_RANGE * CRYS_LAYER_ERROR_IDX) + \ + (CRYS_ERROR_MODULE_RANGE * SRP_ERROR_IDX ) ) + + +/*! EC MONT_EDW module error base address - 0x00F02300. */ +#define CRYS_EC_MONT_EDW_MODULE_ERROR_BASE (CRYS_ERROR_BASE + \ + (CRYS_ERROR_LAYER_RANGE * CRYS_LAYER_ERROR_IDX) + \ + (CRYS_ERROR_MODULE_RANGE * EC_MONT_EDW_ERROR_IDX ) ) + + +/*! User generic error base address - 0x00F50000 */ +#define GENERIC_ERROR_BASE ( CRYS_ERROR_BASE + (CRYS_ERROR_LAYER_RANGE * GENERIC_ERROR_IDX) ) +/*! CRYS fatal error. */ +#define CRYS_FATAL_ERROR (GENERIC_ERROR_BASE + 0x00UL) +/*! CRYS out of resources error. */ +#define CRYS_OUT_OF_RESOURCE_ERROR (GENERIC_ERROR_BASE + 0x01UL) +/*! CRYS illegal resource value error. */ +#define CRYS_ILLEGAL_RESOURCE_VAL_ERROR (GENERIC_ERROR_BASE + 0x02UL) + + + +/* ............ The OK (success) definition ....................... */ +/*! Success defintion. */ +#define CRYS_OK 0 + +/*! MACRO that defines crys return value. */ +#define SASI_CRYS_RETURN_ERROR(retCode, retcodeInfo, funcHandler) \ + ((retCode) == 0 ? CRYS_OK : funcHandler(retCode, retcodeInfo)) + +/************************ Enums ********************************/ + + +/************************ Typedefs ****************************/ + +/*! The typedef definition of all of the error codes that are returned from the CRYS functions */ +typedef uint32_t CRYSError_t; + +/************************ Structs ******************************/ + + +/************************ Public Variables **********************/ + + +/************************ Public Functions **********************/ + +#ifdef __cplusplus +} +#endif +/** +@} + */ +#endif + + + + diff --git a/features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_hash.h b/features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_hash.h new file mode 100644 index 00000000000..ea93a8a8615 --- /dev/null +++ b/features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_hash.h @@ -0,0 +1,285 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + +/*! +@file +@brief This file contains all of the enums and definitions +that are used for the CRYS HASH APIs, as well as the APIs themselves. +@defgroup crys_hash CryptoCell HASH APIs +@{ +@ingroup cryptocell_api + + +This product supports the following HASH algorithms (or modes, according to product): +
  • CRYS_HASH_MD5 (producing 16 byte output).
  • +
  • CRYS_HASH_SHA1 (producing 20 byte output).
  • +
  • CRYS_HASH_SHA224 (producing 28 byte output).
  • +
  • CRYS_HASH_SHA256 (producing 32 byte output).
  • +
  • CRYS_HASH_SHA384 (producing 48 byte output).
  • +
  • CRYS_HASH_SHA512 (producing 64 byte output).
+ +HASH calculation can be performed in either of the following two modes of operation: +
  • Integrated operation - Processes all data in a single function call. This flow is applicable when all data is available prior to the + cryptographic operation.
  • +
  • Block operation - Processes a subset of the data buffers, and is called multiple times in a sequence. This flow is applicable when the + next data buffer becomes available only during/after processing of the current data buffer.
+ +The following is a typical HASH Block operation flow: +
  1. ::CRYS_HASH_Init - this function initializes the HASH machine on the CRYS level by setting the context pointer that is used on the entire + HASH operation.
  2. +
  3. ::CRYS_HASH_Update - this function runs a HASH operation on a block of data allocated by the user. This function may be called as many times + as required.
  4. +
  5. ::CRYS_HASH_Finish - this function ends the HASH operation. It returns the digest result and clears the context.
+*/ + +#ifndef CRYS_HASH_H +#define CRYS_HASH_H + + +#include "ssi_pal_types.h" +#include "crys_error.h" +#include "crys_hash_defs.h" + + +#ifdef __cplusplus +extern "C" +{ +#endif + + +/************************ Defines ******************************/ +/* The hash result in words +#define CRYS_HASH_RESULT_SIZE_IN_WORDS 5*/ +/*! The maximal hash result is 512 bits for SHA512. */ +#define CRYS_HASH_RESULT_SIZE_IN_WORDS 16 + +/*! MD5 digest result size in bytes. */ +#define CRYS_HASH_MD5_DIGEST_SIZE_IN_BYTES 16 + +/*! MD5 digest result size in words. */ +#define CRYS_HASH_MD5_DIGEST_SIZE_IN_WORDS 4 + +/*! SHA-1 digest result size in bytes. */ +#define CRYS_HASH_SHA1_DIGEST_SIZE_IN_BYTES 20 + +/*! SHA-1 digest result size in words. */ +#define CRYS_HASH_SHA1_DIGEST_SIZE_IN_WORDS 5 + +/*! SHA-256 digest result size in words. */ +#define CRYS_HASH_SHA224_DIGEST_SIZE_IN_WORDS 7 + +/*! SHA-256 digest result size in words. */ +#define CRYS_HASH_SHA256_DIGEST_SIZE_IN_WORDS 8 + +/*! SHA-384 digest result size in words. */ +#define CRYS_HASH_SHA384_DIGEST_SIZE_IN_WORDS 12 + +/*! SHA-512 digest result size in words. */ +#define CRYS_HASH_SHA512_DIGEST_SIZE_IN_WORDS 16 + +/*! SHA-256 digest result size in bytes */ +#define CRYS_HASH_SHA224_DIGEST_SIZE_IN_BYTES 28 + +/*! SHA-256 digest result size in bytes */ +#define CRYS_HASH_SHA256_DIGEST_SIZE_IN_BYTES 32 + +/*! SHA-384 digest result size in bytes */ +#define CRYS_HASH_SHA384_DIGEST_SIZE_IN_BYTES 48 + +/*! SHA-512 digest result size in bytes */ +#define CRYS_HASH_SHA512_DIGEST_SIZE_IN_BYTES 64 + +/*! SHA1 hash block size in words */ +#define CRYS_HASH_BLOCK_SIZE_IN_WORDS 16 + +/*! SHA1 hash block size in bytes */ +#define CRYS_HASH_BLOCK_SIZE_IN_BYTES 64 + +/*! SHA2 hash block size in words */ +#define CRYS_HASH_SHA512_BLOCK_SIZE_IN_WORDS 32 + +/*! SHA2 hash block size in bytes */ +#define CRYS_HASH_SHA512_BLOCK_SIZE_IN_BYTES 128 + +/*! Maximal data size for update operation. */ +#define CRYS_HASH_UPDATE_DATA_MAX_SIZE_IN_BYTES (1 << 29) + + +/************************ Enums ********************************/ + +/*! +HASH operation mode +*/ +typedef enum { + CRYS_HASH_SHA1_mode = 0, /*!< SHA1. */ + CRYS_HASH_SHA224_mode = 1, /*!< SHA224. */ + CRYS_HASH_SHA256_mode = 2, /*!< SHA256. */ + CRYS_HASH_SHA384_mode = 3, /*!< SHA384. */ + CRYS_HASH_SHA512_mode = 4, /*!< SHA512. */ + CRYS_HASH_MD5_mode = 5, /*!< MD5. */ + /*! Number of hash modes. */ + CRYS_HASH_NumOfModes, + /*! Reserved. */ + CRYS_HASH_OperationModeLast= 0x7FFFFFFF, + +}CRYS_HASH_OperationMode_t; + +/************************ Typedefs *****************************/ + +/*! HASH result buffer. */ +typedef uint32_t CRYS_HASH_Result_t[CRYS_HASH_RESULT_SIZE_IN_WORDS]; + +/************************ Structs ******************************/ +/*! The user's context prototype - the argument type that is passed by the user + to the HASH APIs. The context saves the state of the operation and must be saved by the user + till the end of the APIs flow. */ +typedef struct CRYS_HASHUserContext_t { + /*! Internal buffer */ + uint32_t buff[CRYS_HASH_USER_CTX_SIZE_IN_WORDS]; +}CRYS_HASHUserContext_t; + +/************************ Public Variables **********************/ + +/************************ Public Functions **********************/ + + +/************************************************************************************************/ +/*! +@brief This function initializes the HASH machine and the HASH Context. + +It receives as input a pointer to store the context handle to the HASH Context, +and initializes the HASH Context with the cryptographic attributes that are needed for the HASH block operation (initializes H's value for the HASH algorithm). + +@return CRYS_OK on success. +@return A non-zero value from crys_hash_error.h on failure. +*/ +CIMPORT_C CRYSError_t CRYS_HASH_Init( + CRYS_HASHUserContext_t *ContextID_ptr, /*!< [in] Pointer to the HASH context buffer allocated by the user that is used + for the HASH machine operation. */ + CRYS_HASH_OperationMode_t OperationMode /*!< [in] One of the supported HASH modes, as defined in CRYS_HASH_OperationMode_t. */ +); + +/************************************************************************************************/ +/*! +@brief This function processes a block of data to be HASHed. + +It updates a HASH Context that was previously initialized by CRYS_HASH_Init or updated by a previous call to CRYS_HASH_Update. + +@return CRYS_OK on success. +@return A non-zero value from crys_hash_error.h on failure. +*/ + +CIMPORT_C CRYSError_t CRYS_HASH_Update( + CRYS_HASHUserContext_t *ContextID_ptr, /*!< [in] Pointer to the HASH context buffer allocated by the user, which is used for the + HASH machine operation. */ + uint8_t *DataIn_ptr, /*!< [in] Pointer to the input data to be HASHed. + it is a one contiguous memory block. */ + size_t DataInSize /*!< [in] Byte size of the input data. Must be > 0. + If not a multiple of the HASH block size (64 for MD5, SHA-1 and SHA-224/256, + 128 for SHA-384/512), no further calls + to CRYS_HASH_Update are allowed in this context, and only CRYS_HASH_Finish + can be called to complete the computation. */ +); + +/************************************************************************************************/ +/*! +@brief This function finalizes the hashing process of data block. + +It receives a handle to the HASH Context, which was previously initialized by CRYS_HASH_Init or by CRYS_HASH_Update. +It "adds" a header to the data block according to the relevant HASH standard, and computes the final message digest. + +@return CRYS_OK on success. +@return A non-zero value from crys_hash_error.h on failure. +*/ + +CIMPORT_C CRYSError_t CRYS_HASH_Finish( + CRYS_HASHUserContext_t *ContextID_ptr, /*!< [in] Pointer to the HASH context buffer allocated by the user that is used for + the HASH machine operation. */ + CRYS_HASH_Result_t HashResultBuff /*!< [in] Pointer to the word-aligned 64 byte buffer. The actual size of the HASH + result depends on CRYS_HASH_OperationMode_t. */ +); + + +/************************************************************************************************/ +/*! +@brief This function is a utility function that frees the context if the operation has failed. + +The function executes the following major steps: +
  1. Checks the validity of all of the inputs of the function.
  2. +
  3. Clears the user's context.
  4. +
  5. Exits the handler with the OK code.
+ +@return CRYS_OK on success. +@return A non-zero value from crys_hash_error.h on failure. +*/ + +CIMPORT_C CRYSError_t CRYS_HASH_Free( + CRYS_HASHUserContext_t *ContextID_ptr /*!< [in] Pointer to the HASH context buffer allocated by the user that is used for + the HASH machine operation. */ +); + + +/************************************************************************************************/ +/*! +@brief This function processes a single buffer of data. + +The function allocates an internal HASH Context, and initializes it with the cryptographic attributes +that are needed for the HASH block operation (initialize H's value for the HASH algorithm). +Then it processes the data block, calculating the HASH. Finally, it returns the data buffer's message digest. + +@return CRYS_OK on success. +@return A non-zero value from crys_hash_error.h on failure. + */ + +CIMPORT_C CRYSError_t CRYS_HASH ( + CRYS_HASH_OperationMode_t OperationMode, /*!< [in] One of the supported HASH modes, as defined in CRYS_HASH_OperationMode_t. */ + uint8_t *DataIn_ptr, /*!< [in] Pointer to the input data to be HASHed. + The size of the scatter/gather list representing the data buffer is limited + to 128 entries, and the size of each entry is limited to 64KB + (fragments larger than 64KB are broken into fragments <= 64KB). */ + size_t DataSize, /*!< [in] The size of the data to be hashed in bytes. */ + CRYS_HASH_Result_t HashResultBuff /*!< [out] Pointer to a word-aligned 64 byte buffer. The actual size of the HASH + result depends on CRYS_HASH_OperationMode_t. */ +); + + + +#ifdef __cplusplus +} +#endif +/** +@} + */ +#endif diff --git a/features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_hash_defs.h b/features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_hash_defs.h new file mode 100644 index 00000000000..701f78a8709 --- /dev/null +++ b/features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_hash_defs.h @@ -0,0 +1,66 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + +#ifndef CRYS_HASH_DEFS_H +#define CRYS_HASH_DEFS_H + +/*! +@file +@brief This file contains HASH definitions. +@defgroup crys_hash_defs CryptoCell Hash definitions +@{ +@ingroup crys_hash +*/ + +#ifdef __cplusplus +extern "C" +{ +#endif + + +/************************ Defines ******************************/ + +/*! The size of user's context prototype (see ::CRYS_HASHUserContext_t) in words. */ +#define CRYS_HASH_USER_CTX_SIZE_IN_WORDS 60 + + +#ifdef __cplusplus +} +#endif + +/** +@} + */ +#endif diff --git a/features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_hash_error.h b/features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_hash_error.h new file mode 100644 index 00000000000..3840d183f76 --- /dev/null +++ b/features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_hash_error.h @@ -0,0 +1,108 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + + + +#ifndef CRYS_HASH_ERROR_H +#define CRYS_HASH_ERROR_H + + +#include "crys_error.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/*! +@file +@brief This module contains the definitions of the CRYS HASH errors. +@defgroup crys_hash_error CryptoCell HASH specific errors +@{ +@ingroup crys_hash +*/ + + + + +/************************ Defines ******************************/ +/*! HASH module on the CRYS layer base address - 0x00F00200*/ +/* The CRYS HASH module errors */ +/*! Illegal context pointer. */ +#define CRYS_HASH_INVALID_USER_CONTEXT_POINTER_ERROR (CRYS_HASH_MODULE_ERROR_BASE + 0x0UL) +/*! Illegal operation mode. */ +#define CRYS_HASH_ILLEGAL_OPERATION_MODE_ERROR (CRYS_HASH_MODULE_ERROR_BASE + 0x1UL) +/*! Context is corrupted. */ +#define CRYS_HASH_USER_CONTEXT_CORRUPTED_ERROR (CRYS_HASH_MODULE_ERROR_BASE + 0x2UL) +/*! Illegal data in pointer. */ +#define CRYS_HASH_DATA_IN_POINTER_INVALID_ERROR (CRYS_HASH_MODULE_ERROR_BASE + 0x3UL) +/*! Illegal data in size. */ +#define CRYS_HASH_DATA_SIZE_ILLEGAL (CRYS_HASH_MODULE_ERROR_BASE + 0x4UL) +/*! Illegal result buffer pointer. */ +#define CRYS_HASH_INVALID_RESULT_BUFFER_POINTER_ERROR (CRYS_HASH_MODULE_ERROR_BASE + 0x5UL) +/*! Last block was already processed (may happen if previous block was not a multiple of block size). */ +#define CRYS_HASH_LAST_BLOCK_ALREADY_PROCESSED_ERROR (CRYS_HASH_MODULE_ERROR_BASE + 0xCUL) +/*! Illegal parameter. */ +#define CRYS_HASH_ILLEGAL_PARAMS_ERROR (CRYS_HASH_MODULE_ERROR_BASE + 0xDUL) +/*! Illegal context size. */ +#define CRYS_HASH_CTX_SIZES_ERROR (CRYS_HASH_MODULE_ERROR_BASE + 0xEUL) +/*! HASH is not supported. */ +#define CRYS_HASH_IS_NOT_SUPPORTED (CRYS_HASH_MODULE_ERROR_BASE + 0xFUL) + + + +/************************ Enums ********************************/ + + +/************************ Typedefs ****************************/ + + +/************************ Structs ******************************/ + + +/************************ Public Variables **********************/ + + +/************************ Public Functions **********************/ + +#ifdef __cplusplus +} +#endif +/** +@} + */ +#endif + + diff --git a/features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_hkdf.h b/features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_hkdf.h new file mode 100644 index 00000000000..fbc5bcc5557 --- /dev/null +++ b/features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_hkdf.h @@ -0,0 +1,124 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + +#ifndef CRYS_HKDF_H +#define CRYS_HKDF_H + +#include "crys_hash.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/*! +@file +@brief This module defines the API that supports HMAC Key derivation function as defined by RFC5869. +@defgroup crys_hkdf CryptoCell HMAC Key Derivation APIs +@{ +@ingroup cryptocell_api +*/ + +/*! HKDF maximal key size in words. */ +#define CRYS_HKDF_MAX_HASH_KEY_SIZE_IN_BYTES 512 + +/*! HKDF maximal HASH digest size in bytes. */ +#define CRYS_HKDF_MAX_HASH_DIGEST_SIZE_IN_BYTES CRYS_HASH_SHA512_DIGEST_SIZE_IN_BYTES + +/************************ Defines ******************************/ + +/************************ Enums ********************************/ + +/*! Enum defining HKDF HASH available modes. */ +typedef enum +{ + /*! SHA1 mode. */ + CRYS_HKDF_HASH_SHA1_mode = 0, + /*! SHA224 mode. */ + CRYS_HKDF_HASH_SHA224_mode = 1, + /*! SHA256 mode. */ + CRYS_HKDF_HASH_SHA256_mode = 2, + /*! SHA384 mode. */ + CRYS_HKDF_HASH_SHA384_mode = 3, + /*! SHA512 mode. */ + CRYS_HKDF_HASH_SHA512_mode = 4, + + /*! Maximal number of HASH modes. */ + CRYS_HKDF_HASH_NumOfModes, + + /*! Reserved */ + CRYS_HKDF_HASH_OpModeLast = 0x7FFFFFFF, + +}CRYS_HKDF_HASH_OpMode_t; + +/************************ Typedefs ****************************/ + +/************************ Structs ******************************/ + +/************************ Public Variables **********************/ + +/************************ Public Functions **********************/ + +/****************************************************************/ + + +/*********************************************************************************************************/ +/*! +@brief CRYS_HKDF_KeyDerivFunc performs the HMAC-based key derivation, according to RFC5869 + +@return CRYS_OK on success. +@return A non-zero value on failure as defined crys_kdf_error.h, crys_hash_error or crys_hmac_error.h +*/ +CEXPORT_C CRYSError_t CRYS_HKDF_KeyDerivFunc( + CRYS_HKDF_HASH_OpMode_t HKDFhashMode, /*!< [in] The HKDF identifier of hash function to be used. */ + uint8_t* Salt_ptr, /*!< [in] A pointer to a non secret random value. can be NULL. */ + size_t SaltLen, /*!< [in] The size of the salt_ptr. */ + uint8_t* Ikm_ptr, /*!< [in] A pointer to a input key message. */ + uint32_t IkmLen, /*!< [in] The size of the input key message */ + uint8_t* Info, /*!< [in] A pointer to an optional context and application specific information. can be NULL */ + uint32_t InfoLen, /*!< [in] The size of the info. */ + uint8_t* Okm, /*!< [in] A pointer to a output key material. */ + uint32_t OkmLen, /*!< [in] The size of the output key material. */ + SaSiBool IsStrongKey /*!< [in] if TRUE , then no need to perform the extraction phase. */ + ); + +#ifdef __cplusplus +} +#endif +/** +@} + */ +#endif + diff --git a/features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_hkdf_error.h b/features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_hkdf_error.h new file mode 100644 index 00000000000..d78398e32f9 --- /dev/null +++ b/features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_hkdf_error.h @@ -0,0 +1,91 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + +#ifndef CRYS_HKDF_ERROR_H +#define CRYS_HKDF_ERROR_H + +#include "crys_error.h" + + +#ifdef __cplusplus +extern "C" +{ +#endif + +/*! +@file +@brief This module contains the definitions of the CRYS HKDF errors. +@defgroup crys_hkdf_error HMAC Key Derivation specific errors +@{ +@ingroup crys_hkdf + */ + + +/************************ Defines *******************************/ + +/*! CryptoCell HKDF module errors / base address - 0x00F01100. */ +/*! Invalid argument. */ +#define CRYS_HKDF_INVALID_ARGUMENT_POINTER_ERROR (CRYS_HKDF_MODULE_ERROR_BASE + 0x0UL) +/*! Invalid argument size. */ +#define CRYS_HKDF_INVALID_ARGUMENT_SIZE_ERROR (CRYS_HKDF_MODULE_ERROR_BASE + 0x1UL) +/*! Illegal hash mode. */ +#define CRYS_HKDF_INVALID_ARGUMENT_HASH_MODE_ERROR (CRYS_HKDF_MODULE_ERROR_BASE + 0x3UL) +/*! HKDF not supported. */ +#define CRYS_HKDF_IS_NOT_SUPPORTED (CRYS_HKDF_MODULE_ERROR_BASE + 0xFFUL) + +/************************ Enums *********************************/ + +/************************ Typedefs *****************************/ + +/************************ Structs ******************************/ + +/************************ Public Variables **********************/ + +/************************ Public Functions **********************/ + + + + +#ifdef __cplusplus +} +#endif +/** +@} + */ +#endif + + + + diff --git a/features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_hmac.h b/features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_hmac.h new file mode 100644 index 00000000000..9094d732ef2 --- /dev/null +++ b/features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_hmac.h @@ -0,0 +1,214 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + +/*! +@file +@brief This file contains all of the enums and definitions +that are used for the CRYS HMAC APIs, as well as the APIs themselves. +@defgroup crys_hmac CryptoCell HMAC APIs +@{ +@ingroup cryptocell_api + + +HMAC is a wrapping algorithm that uses a HASH function (one of the supported HASH algorithms, as specified in the HASH chapter) and a key, +to generate a unique authentication code over the input data. +HMAC calculation can be performed in either of the following two modes of operation: +
  • Integrated operation - Processes all data in a single function call. This flow is applicable when all data is available prior to +the cryptographic operation.
  • +
  • Block operation - Processes a subset of the data buffers, and is called multiple times in a sequence. This flow is applicable when +the next data buffer becomes available only during/after processing of the current data buffer.
+ +The following is a typical HMAC Block operation flow: +
  1. ::CRYS_HMAC_Init: This function initializes the HMAC machine on the CRYS level by setting the context pointer that is + used on the entire HMAC operation.
  2. +
  3. ::CRYS_HMAC_Update: This function runs an HMAC operation on a block of data allocated by the user. This function may be called as + many times as required.
  4. +
  5. ::CRYS_HMAC_Finish: This function ends the HMAC operation. It returns the digest result and clears the context.
+*/ + +#ifndef CRYS_HMAC_H +#define CRYS_HMAC_H + + +#include "ssi_pal_types.h" +#include "crys_error.h" + +#include "crys_hash.h" +#include "crys_hmac_defs.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + + +/************************ Defines ******************************/ + +/*! HMAC key size after padding for MD5, SHA1, SHA256. */ +#define CRYS_HMAC_KEY_SIZE_IN_BYTES 64 + +/*! HMAC key size after padding for SHA384, SHA512 */ +#define CRYS_HMAC_SHA2_1024BIT_KEY_SIZE_IN_BYTES 128 + +/************************ Enums ********************************/ + +/************************ Typedefs ****************************/ + +/*********************** Structures ****************************/ + + +/*! User's context prototype - the argument type that is passed by the user + to the HMAC APIs. The context saves the state of the operation and must be saved by the user + till the end of the APIs flow */ +typedef struct CRYS_HMACUserContext_t { + /*! Context buffer for internal use */ + uint32_t buff[CRYS_HMAC_USER_CTX_SIZE_IN_WORDS]; + +}CRYS_HMACUserContext_t; + +/************************ Structs ******************************/ + + +/************************ Public Variables **********************/ + + +/************************ Public Functions **********************/ + +/*! +@brief This function initializes the HMAC machine. + +It allocates and initializes the HMAC Context. It initiates a HASH session and processes a HASH update on the Key XOR ipad, +then stores it in the context + +@return CRYS_OK on success. +@return A non-zero value from crys_hmac_error.h or crys_hash_error.h on failure. +*/ +CIMPORT_C CRYSError_t CRYS_HMAC_Init( + CRYS_HMACUserContext_t *ContextID_ptr, /*!< [in] Pointer to the HMAC context buffer allocated by the user, which is used + for the HMAC machine operation. */ + CRYS_HASH_OperationMode_t OperationMode, /*!< [in] One of the supported HASH modes, as defined in CRYS_HASH_OperationMode_t. */ + uint8_t *key_ptr, /*!< [in] The pointer to the user's key buffer. */ + uint16_t keySize /*!< [in] The key size in bytes. If the key size is bigger than the HASH block, the key will be hashed. + The limitations on the key size are the same as the limitations on MAX hash size. */ +); + + +/*! +@brief This function processes a block of data to be HASHed. + +It receives a handle to the HMAC Context, and updates the HASH value with the new data. + +@return CRYS_OK on success. +@return A non-zero value from crys_hmac_error.h or crys_hash_error.h on failure. +*/ + +CIMPORT_C CRYSError_t CRYS_HMAC_Update( + CRYS_HMACUserContext_t *ContextID_ptr, /*!< [in] Pointer to the HMAC context buffer allocated by the user + that is used for the HMAC machine operation. */ + uint8_t *DataIn_ptr, /*!< [in] Pointer to the input data to be HASHed. + The size of the scatter/gather list representing the data buffer is limited to + 128 entries, and the size of each entry is limited to 64KB + (fragments larger than 64KB are broken into fragments <= 64KB). */ + size_t DataInSize /*!< [in] Byte size of the input data. Must be > 0. + If not a multiple of the HASH block size (64 for SHA-1 and SHA-224/256, + 128 for SHA-384/512), no further calls to ::CRYS_HMAC_Update are allowed in + this context, and only ::CRYS_HMAC_Finish can be called to complete the + computation. */ +); + + +/*! +@brief This function finalizes the HMAC processing of a data block. + +It receives a handle to the HMAC context that was previously initialized by ::CRYS_HMAC_Init, or by ::CRYS_HMAC_Update. +It completes the HASH calculation on the ipad and text, and then executes a new HASH operation with the key XOR opad and the previous +HASH operation result. + +@return CRYS_OK on success. +@return A non-zero value from crys_hmac_error.h or crys_hash_error.h on failure. +*/ + +CIMPORT_C CRYSError_t CRYS_HMAC_Finish( + CRYS_HMACUserContext_t *ContextID_ptr, /*!< [in] Pointer to the HMAC context buffer allocated by the user, which is used + for the HMAC machine operation. */ + CRYS_HASH_Result_t HmacResultBuff /*!< [out] Pointer to the word-aligned 64 byte buffer. The actual size of the + HASH result depends on CRYS_HASH_OperationMode_t. */ +); + + +/*! +@brief This function is a service function that frees the context if the operation has failed. + +The function executes the following major steps: +
  1. Checks the validity of all of the inputs of the function.
  2. +
  3. Clears the user's context.
  4. +
  5. Exits the handler with the OK code.
+ +@return CRYS_OK on success. +@return a non-zero value from crys_hmac_error.h on failure. +*/ + +CIMPORT_C CRYSError_t CRYS_HMAC_Free( + CRYS_HMACUserContext_t *ContextID_ptr /*!< [in] Pointer to the HMAC context buffer allocated by the user, which is used for + the HMAC machine operation. */ +); + + +/*! +@brief This function processes a single buffer of data, and returns the data buffer's message digest. + +@return CRYS_OK on success. +@return A non-zero value from crys_hmac_error.h or crys_hash_error.h on failure. +*/ +CIMPORT_C CRYSError_t CRYS_HMAC ( + CRYS_HASH_OperationMode_t OperationMode, /*!< [in] One of the supported HASH modes, as defined in CRYS_HASH_OperationMode_t. */ + uint8_t *key_ptr, /*!< [in] The pointer to the user's key buffer. */ + uint16_t keySize, /*!< [in] The key size in bytes. If the key size is bigger than the HASH block, the key will be hashed. + The limitations on the key size are the same as the limitations on MAX hash size.*/ + uint8_t *DataIn_ptr, /*!< [in] Pointer to the input data to be HASHed. + The size of the scatter/gather list representing the data buffer is limited to 128 + entries, and the size of each entry is limited to 64KB (fragments larger than + 64KB are broken into fragments <= 64KB). */ + size_t DataSize, /*!< [in] The size of the data to be hashed (in bytes). */ + CRYS_HASH_Result_t HmacResultBuff /*!< [out] Pointer to the word-aligned 64 byte buffer. The actual size of the + HMAC result depends on CRYS_HASH_OperationMode_t. */ +); +#ifdef __cplusplus +} +#endif +/** +@} + */ +#endif diff --git a/features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_hmac_defs.h b/features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_hmac_defs.h new file mode 100644 index 00000000000..6e76d71988a --- /dev/null +++ b/features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_hmac_defs.h @@ -0,0 +1,64 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + +#ifndef CRYS_HMAC_DEFS_H +#define CRYS_HMAC_DEFS_H + + +#ifdef __cplusplus +extern "C" +{ +#endif + +/*! +@file +@brief This file contains HMAC definitions. +@defgroup crys_hmac_defs CryptoCell Hmac definitions +@{ +@ingroup crys_hmac +*/ + +/************************ Defines ******************************/ +/*! The size of user's context prototype (see ::CRYS_HMACUserContext_t) in words. */ +#define CRYS_HMAC_USER_CTX_SIZE_IN_WORDS 94 + + +#ifdef __cplusplus +} +#endif +/** +@} + */ +#endif diff --git a/features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_hmac_error.h b/features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_hmac_error.h new file mode 100644 index 00000000000..e9bd5c8b2f7 --- /dev/null +++ b/features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_hmac_error.h @@ -0,0 +1,108 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + + +#ifndef CRYS_HMAC_ERROR_H +#define CRYS_HMAC_ERROR_H + +#include "crys_error.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/*! @file +@brief This module contains the definitions of the CRYS HMAC errors. +@defgroup crys_hmac_error CryptoCell HMAC specific errors +@{ +@ingroup crys_hmac +*/ + + + +/************************ Defines ******************************/ + +/*! The CRYS HMAC module errors */ +/*! Illegal context pointer. */ +#define CRYS_HMAC_INVALID_USER_CONTEXT_POINTER_ERROR (CRYS_HMAC_MODULE_ERROR_BASE + 0x0UL) +/*! Illegal operation mode. */ +#define CRYS_HMAC_ILLEGAL_OPERATION_MODE_ERROR (CRYS_HMAC_MODULE_ERROR_BASE + 0x1UL) +/*! Context is corrupted. */ +#define CRYS_HMAC_USER_CONTEXT_CORRUPTED_ERROR (CRYS_HMAC_MODULE_ERROR_BASE + 0x2UL) +/*! Illegal data in pointer. */ +#define CRYS_HMAC_DATA_IN_POINTER_INVALID_ERROR (CRYS_HMAC_MODULE_ERROR_BASE + 0x3UL) +/*! Illegal data in size. */ +#define CRYS_HMAC_DATA_SIZE_ILLEGAL (CRYS_HMAC_MODULE_ERROR_BASE + 0x4UL) +/*! Illegal result buffer pointer. */ +#define CRYS_HMAC_INVALID_RESULT_BUFFER_POINTER_ERROR (CRYS_HMAC_MODULE_ERROR_BASE + 0x5UL) +/*! Illegal key buffer pointer. */ +#define CRYS_HMAC_INVALID_KEY_POINTER_ERROR (CRYS_HMAC_MODULE_ERROR_BASE + 0x6UL) +/*! Illegal key size. */ +#define CRYS_HMAC_UNVALID_KEY_SIZE_ERROR (CRYS_HMAC_MODULE_ERROR_BASE + 0x7UL) +/*! Last block was already processed (may happen if previous block was not a multiple of block size). */ +#define CRYS_HMAC_LAST_BLOCK_ALREADY_PROCESSED_ERROR (CRYS_HMAC_MODULE_ERROR_BASE + 0xBUL) +/*! Illegal parameters. */ +#define CRYS_HMAC_ILLEGAL_PARAMS_ERROR (CRYS_HMAC_MODULE_ERROR_BASE + 0xCUL) +/*! Illegal context size. */ +#define CRYS_HMAC_CTX_SIZES_ERROR (CRYS_HMAC_MODULE_ERROR_BASE + 0xEUL) +/*! HMAC is not supported. */ +#define CRYS_HMAC_IS_NOT_SUPPORTED (CRYS_HMAC_MODULE_ERROR_BASE + 0xFUL) + + + +/************************ Enums ********************************/ + + +/************************ Typedefs ****************************/ + + +/************************ Structs ******************************/ + + +/************************ Public Variables **********************/ + + +/************************ Public Functions **********************/ + +#ifdef __cplusplus +} +#endif +/** +@} + */ +#endif + + diff --git a/features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_kdf.h b/features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_kdf.h new file mode 100644 index 00000000000..add338e2f39 --- /dev/null +++ b/features/mbedtls/targets/TARGET_CRYPTOCELL310/include/crys_kdf.h @@ -0,0 +1,211 @@ +/************************************************************************************** +* Copyright (c) 2016-2017, ARM Limited or its affiliates. All rights reserved * +* * +* This file and the related binary are licensed under the following license: * +* * +* ARM Object Code and Header Files License, v1.0 Redistribution. * +* * +* Redistribution and use of object code, header files, and documentation, without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1) Redistributions must reproduce the above copyright notice and the * +* following disclaimer in the documentation and/or other materials * +* provided with the distribution. * +* * +* 2) Unless to the extent explicitly permitted by law, no reverse * +* engineering, decompilation, or disassembly of is permitted. * +* * +* 3) Redistribution and use is permitted solely for the purpose of * +* developing or executing applications that are targeted for use * +* on an ARM-based product. * +* * +* DISCLAIMER. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND * +* CONTRIBUTORS "AS IS." ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * +* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, * +* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * +* COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * +* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * +* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * +* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * +* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +**************************************************************************************/ + + +#ifndef CRYS_KDF_H +#define CRYS_KDF_H + + +#include "crys_hash.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/*! +@file +@brief This module defines the API that supports Key derivation function in modes +as defined in PKCS#3, ANSI X9.42-2001, and ANSI X9.63-1999. +@defgroup crys_kdf CryptoCell Key Derivation APIs +@{ +@ingroup cryptocell_api +*/ + +#include "crys_hash.h" + +/************************ Defines ******************************/ + +/*! Shared secret value max size in bytes */ +#define CRYS_KDF_MAX_SIZE_OF_SHARED_SECRET_VALUE 1024 + +/* Count and max. sizeof OtherInfo entries (pointers to data buffers) */ +/*! Number of other info entries. */ +#define CRYS_KDF_COUNT_OF_OTHER_INFO_ENTRIES 5 +/*! Maximal size of other info entry. */ +#define CRYS_KDF_MAX_SIZE_OF_OTHER_INFO_ENTRY 64 /*!< Size is in bytes*/ +/*! Maximal size of keying data in bytes. */ +#define CRYS_KDF_MAX_SIZE_OF_KEYING_DATA 2048 + +/************************ Enums ********************************/ +/*! HASH operation modes */ +typedef enum +{ + /*! SHA1 mode.*/ + CRYS_KDF_HASH_SHA1_mode = 0, + /*! SHA224 mode.*/ + CRYS_KDF_HASH_SHA224_mode = 1, + /*! SHA256 mode.*/ + CRYS_KDF_HASH_SHA256_mode = 2, + /*! SHA384 mode.*/ + CRYS_KDF_HASH_SHA384_mode = 3, + /*! SHA512 mode.*/ + CRYS_KDF_HASH_SHA512_mode = 4, + /*! Maximal number of HASH modes. */ + CRYS_KDF_HASH_NumOfModes, + /*! Reserved.*/ + CRYS_KDF_HASH_OpModeLast = 0x7FFFFFFF, + +}CRYS_KDF_HASH_OpMode_t; + +/*! Key derivation modes. */ +typedef enum +{ + /*! ASN1 key derivation mode.*/ + CRYS_KDF_ASN1_DerivMode = 0, + /*! Concatination key derivation mode.*/ + CRYS_KDF_ConcatDerivMode = 1, + /*! X963 key derivation mode.*/ + CRYS_KDF_X963_DerivMode = CRYS_KDF_ConcatDerivMode, + /*! ISO 18033 KDF1 key derivation mode.*/ + CRYS_KDF_ISO18033_KDF1_DerivMode = 3, + /*! ISO 18033 KDF2 key derivation mode.*/ + CRYS_KDF_ISO18033_KDF2_DerivMode = 4, + /*! Maximal number of key derivation modes. */ + CRYS_KDF_DerivFunc_NumOfModes = 5, + /*! Reserved.*/ + CRYS_KDF_DerivFuncModeLast= 0x7FFFFFFF, + +}CRYS_KDF_DerivFuncMode_t; + +/************************ Typedefs ****************************/ + +/*! Structure, containing the optional data (other info) for KDF, + if any data is not needed, then the pointer value and + the size must be set to NULL */ +typedef struct +{ + /*! A unique object identifier (OID), indicating algorithm(s) + for which the keying data is used. */ + uint8_t AlgorithmID[CRYS_KDF_MAX_SIZE_OF_OTHER_INFO_ENTRY]; + uint32_t SizeOfAlgorithmID; /*!< Size of algorithm ID.*/ + /*! Public information contributed by the initiator. */ + uint8_t PartyUInfo[CRYS_KDF_MAX_SIZE_OF_OTHER_INFO_ENTRY]; + uint32_t SizeOfPartyUInfo; /*!< Size of the Public information contributed by the initiator. */ + /*! Public information contributed by the responder. */ + uint8_t PartyVInfo[CRYS_KDF_MAX_SIZE_OF_OTHER_INFO_ENTRY]; + uint32_t SizeOfPartyVInfo; /*!< Size of the responder's public information. */ + /*! Mutually-known private information, e.g. shared information + communicated throgh a separate channel. */ + uint8_t SuppPrivInfo[CRYS_KDF_MAX_SIZE_OF_OTHER_INFO_ENTRY]; + uint32_t SizeOfSuppPrivInfo; /*!< Size of the private information. */ + /*! Mutually-known public information, */ + uint8_t SuppPubInfo[CRYS_KDF_MAX_SIZE_OF_OTHER_INFO_ENTRY]; + uint32_t SizeOfSuppPubInfo; /*!< Size of the public information. */ + +}CRYS_KDF_OtherInfo_t; + +/************************ Structs ******************************/ + +/************************ Public Variables **********************/ + +/************************ Public Functions **********************/ + +/****************************************************************/ + + +/*********************************************************************************************************/ +/*! + @brief CRYS_KDF_KeyDerivFunc performs key derivation according to one of the modes defined in standards: + ANS X9.42-2001, ANS X9.63, ISO/IEC 18033-2. + +The present implementation of the function allows the following operation modes: +
  • CRYS_KDF_ASN1_DerivMode - mode based on ASN.1 DER encoding;
  • +
  • CRYS_KDF_ConcatDerivMode - mode based on concatenation;
  • +
  • CRYS_KDF_X963_DerivMode = CRYS_KDF_ConcatDerivMode;
  • +
  • CRYS_KDF_ISO18033_KDF1_DerivMode - specific mode according to ECIES-KEM algorithm (ISO/IEC 18033-2).
+ +The purpose of this function is to derive a keying data from the shared secret value and some +other optional shared information (SharedInfo). + +\note +