Compare commits
680 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e3bb51cb23 | |||
| f21650709a | |||
| 5c4271f7cb | |||
| 5ef40c60f6 | |||
| 2c46c10631 | |||
| 302b818d4b | |||
| 8fc2dc07d8 | |||
| e7848220a2 | |||
| 7cc3f4fce0 | |||
| 4512b792ba | |||
| 808f832917 | |||
| f60bcfb3ef | |||
| 68a0b1b112 | |||
| e2daba6d20 | |||
| 331d2cee0a | |||
| 65b87ce4f6 | |||
| 388dfa187f | |||
| 32524c93b3 | |||
| 1a66326f09 | |||
| e2568c41cb | |||
| 6df7667f94 | |||
| 3e2001c767 | |||
| 72912d2500 | |||
| e976887412 | |||
| 5600c58f82 | |||
| ae9f0616c5 | |||
| 34bf605c19 | |||
| 874c73804a | |||
| 02b1d1953a | |||
| 18cdde7cc9 | |||
| f4ecc84644 | |||
| 78f5e75739 | |||
| 488ca0eace | |||
| e1bfd16dd7 | |||
| 348f0d8db9 | |||
| bd70845a80 | |||
| ca9e8f52f1 | |||
| 74115c93f1 | |||
| 8c44afd2c9 | |||
| 83d1a3d3c8 | |||
| 4a37de076b | |||
| 70dbf042b6 | |||
| 590b677d48 | |||
| f6ae9e6c2c | |||
| 016ebe2d0e | |||
| 7934f08b26 | |||
| 8f94c31b19 | |||
| ba2d3df759 | |||
| e3dee27f9c | |||
| 9bbdf5832d | |||
| ef37ab5919 | |||
| d8ea3902b5 | |||
| 26ababbf65 | |||
| c90be3b143 | |||
| dc110f5145 | |||
| 4492a61567 | |||
| 78b8b99cf7 | |||
| bda7b9adfa | |||
| 211a06afef | |||
| 8d200744b4 | |||
| b0c761eb76 | |||
| 27e377ec65 | |||
| 6c5454704c | |||
| 921aba3c09 | |||
| 37af90f721 | |||
| d272dea99b | |||
| 9fb6feaa84 | |||
| a4cb62f0ae | |||
| d363247f1e | |||
| 4d1b57ae7f | |||
| ee910bfe24 | |||
| abbf365b6d | |||
| 182b573329 | |||
| 6e9321f9ae | |||
| 61c9838d2d | |||
| e6c58ffa70 | |||
| 7b6acc5cb5 | |||
| 2916430ddb | |||
| 4d2e1a8fb8 | |||
| af2b1e8210 | |||
| ec783839be | |||
| d4e37951b4 | |||
| edad306de9 | |||
| 0121953a10 | |||
| 9a89250285 | |||
| 2507d9e709 | |||
| 13fafcd32a | |||
| ccf80574e9 | |||
| a6b8689dc9 | |||
| 10e1060261 | |||
| 22df69103f | |||
| 6d81cf3d9c | |||
| 506be38be1 | |||
| 56851c85f3 | |||
| e664a534af | |||
| 2eee131401 | |||
| d6a8a5a54d | |||
| 9ad98f7edf | |||
| 17c3057f26 | |||
| c937699735 | |||
| c642aca28f | |||
| ebb4a37ed2 | |||
| 9f9f4eaa2e | |||
| 6dc8bf6262 | |||
| bf1117d1fd | |||
| 31b0c9be30 | |||
| 8f28886817 | |||
| e39ac8fb59 | |||
| 1386aad102 | |||
| 59392c360d | |||
| cfc11c2320 | |||
| 86e95b852e | |||
| 0e4a448ab8 | |||
| 6f2cd5d5c2 | |||
| 7d53638872 | |||
| 71dfad4d10 | |||
| 3a1dd46e4e | |||
| 7e9e06a739 | |||
| c5304e4f3b | |||
| 818031ec17 | |||
| 11d11d6184 | |||
| 09ed11928e | |||
| 14308731e5 | |||
| a3d76d019f | |||
| 9f2bffbb72 | |||
| b853f315dd | |||
| c66e397106 | |||
| c386440683 | |||
| 03fe3697f7 | |||
| 2abda63a4f | |||
| 3ba4fb47e6 | |||
| dbe01585ba | |||
| 6fb16cc93d | |||
| 8a5dcbcaaa | |||
| 4a8d1f3519 | |||
| c6d4af0098 | |||
| d304a2f1ac | |||
| 81678aabd7 | |||
| 0238d8f4ff | |||
| b609c22882 | |||
| f526081100 | |||
| 81a5df4d60 | |||
| e64d2c74fa | |||
| d781fc424b | |||
| e8703a3708 | |||
| a93a68d3cd | |||
| 52586f952e | |||
| 812b197ae1 | |||
| 1ffb4a4283 | |||
| a502239475 | |||
| 038da9b939 | |||
| 9d4e06e6bc | |||
| b0651775c2 | |||
| 08fea48a91 | |||
| 96ee4a8103 | |||
| 0b80f7f287 | |||
| 8d43674b8e | |||
| 520e1220bb | |||
| a818134b67 | |||
| be483dbe2d | |||
| ee7aa02744 | |||
| d9cbb53562 | |||
| 2ec3b31548 | |||
| 35dd4c8fcd | |||
| 13f1f17b43 | |||
| d68618b21e | |||
| fed35d3224 | |||
| d2e872faf4 | |||
| 00019f2193 | |||
| a1ce85696d | |||
| bf5f192310 | |||
| 634f475255 | |||
| 99a93d4327 | |||
| c3648faaa7 | |||
| 364af78407 | |||
| eb083b0d35 | |||
| 413e79e947 | |||
| 7d7ed9f51b | |||
| cd4d981bba | |||
| 09114ae285 | |||
| 9343b0b8b3 | |||
| 0fde2eb0e3 | |||
| 04017c17db | |||
| e59703c72b | |||
| a6bae93bf8 | |||
| c94998ae95 | |||
| 353577cdc7 | |||
| 8f36c51f98 | |||
| 06a6ed0170 | |||
| a93bc1124c | |||
| 97ca762b2a | |||
| 2b0444e01d | |||
| 0cf201e917 | |||
| 3c9729212b | |||
| d977eaa125 | |||
| 74bce29965 | |||
| 946dd62ac0 | |||
| 3120950b1e | |||
| 5df5be1a4b | |||
| 5aaaa98f8c | |||
| bfd94db72c | |||
| e55b32ddff | |||
| 6fff386492 | |||
| cd60bf0e0a | |||
| 05d4c9727f | |||
| 44c0772c80 | |||
| 0a9bf669db | |||
| 773ae91d0e | |||
| 68161cb8ba | |||
| fc08dfc4cd | |||
| 4414874f1f | |||
| babcac1c6f | |||
| 9961dff055 | |||
| 0d1730ddf1 | |||
| b5f55c3afb | |||
| 9b6ff440ef | |||
| d98107b4e1 | |||
| 8d606e361c | |||
| 72b36cfed8 | |||
| 0a20f7860b | |||
| a75fc71055 | |||
| ca7435822f | |||
| 289e76b6ff | |||
| 0391f16673 | |||
| e831a81518 | |||
| 24e5886c0e | |||
| 5e578c9dba | |||
| 8379978bc8 | |||
| 0a3663a64f | |||
| 3763cbeb6a | |||
| f03cdc3a93 | |||
| 8da59555c6 | |||
| b9940a649a | |||
| ae96383af3 | |||
| e2ff2ca0dc | |||
| 7f7ef53e68 | |||
| 43a4092414 | |||
| c07635f869 | |||
| 0514e3dfdd | |||
| b529253bea | |||
| 6af3a3d9ed | |||
| 19670949ca | |||
| ff2394527f | |||
| 18d9f28f0d | |||
| 1845d0dbdb | |||
| 2dfa1ba680 | |||
| 5e61d533c9 | |||
| c40e1830ac | |||
| 656aa9a262 | |||
| f6584e7a52 | |||
| 42adba5173 | |||
| 3b33f3eb2d | |||
| 619b323a5e | |||
| 21882c5c75 | |||
| 204b8a115d | |||
| a09a65ffdb | |||
| 16c3f06eb0 | |||
| e7d6988c25 | |||
| 9f579bfe6c | |||
| 3d14a15eef | |||
| 17ce286e07 | |||
| d91e1efd83 | |||
| 54581cc60f | |||
| 8ba6a1496b | |||
| ce9f6937e2 | |||
| a26001b902 | |||
| 0da939d3a9 | |||
| f6e5b1f293 | |||
| 055375ef26 | |||
| b0bb83a583 | |||
| e8ee947004 | |||
| cb34f8695d | |||
| 6da9eaeef1 | |||
| 6758d043bb | |||
| a51912f7fe | |||
| 2b56981b64 | |||
| e345f9b6d5 | |||
| cd334a54ca | |||
| 733f46e84f | |||
| c5e9ac1cac | |||
| 6757fbf8e3 | |||
| b22e15c33c | |||
| 2c84a469b0 | |||
| c655cb7bf9 | |||
| b89e025cfa | |||
| 0ffc795efb | |||
| d79bc9d397 | |||
| 563924bebd | |||
| 592af53963 | |||
| 7f07fb2b5a | |||
| f64a6eeaf0 | |||
| 2f3404bb81 | |||
| 2d04cf08cb | |||
| 7c075b99e2 | |||
| 68f84f5c40 | |||
| 806e18c022 | |||
| 59e1a81871 | |||
| e7d3922b43 | |||
| d94682dce5 | |||
| 21cb0744bb | |||
| 03c6fa4426 | |||
| e324de004a | |||
| 8c2e8282ab | |||
| 3ecd0a5fca | |||
| 8726d8fe0c | |||
| 1f1eeeade2 | |||
| ef374b8692 | |||
| dfef2081f3 | |||
| 01f8a8c2d5 | |||
| 894e20039d | |||
| 429e85b516 | |||
| 5f107ce4d8 | |||
| d55bd797eb | |||
| 250542312b | |||
| 118355c6f0 | |||
| c49c9e7e61 | |||
| a4f7cc206f | |||
| b3aaffae15 | |||
| 467d3220f8 | |||
| 1ac4f16fe9 | |||
| 208e239371 | |||
| 4dcc290eb0 | |||
| b056ed304d | |||
| 48b6b8f00f | |||
| 39655ef01a | |||
| 2f238d981a | |||
| 866c219432 | |||
| 391cc8c7a1 | |||
| 583c12ea97 | |||
| c5388a1cd1 | |||
| 44ccadc825 | |||
| c4dfc6f4c8 | |||
| fee8559162 | |||
| 18ffb16b6a | |||
| ad50a0d7cd | |||
| 82a83ff577 | |||
| 768e6822cc | |||
| edafe47968 | |||
| 43e5a26b53 | |||
| c5f0c16b61 | |||
| 1e5cb820de | |||
| 799676c998 | |||
| ebc4de6719 | |||
| 63a13ac6fa | |||
| ce3ec70edf | |||
| d4847c6d96 | |||
| 0402f89448 | |||
| 74cd5d98cc | |||
| 08ab59b8d7 | |||
| 1d59f6e3e2 | |||
| 8b0515b0f1 | |||
| f99d2c6141 | |||
| 873ebc9783 | |||
| 93731d9dd4 | |||
| 20d202bb0e | |||
| e838cfb51f | |||
| 95511e9842 | |||
| 0d5b886ef8 | |||
| 4d1f4ba08d | |||
| 4c7b3bfd73 | |||
| 238148a8f6 | |||
| c0485d67f4 | |||
| c862c31f4c | |||
| 4323e22793 | |||
| e34eaa6409 | |||
| 45dd8a04f5 | |||
| 2e2a226ac9 | |||
| 4249481a66 | |||
| a90044a463 | |||
| b0521e38d2 | |||
| bf21849e3d | |||
| 96dec443d9 | |||
| aacb72c1b7 | |||
| ac52908e59 | |||
| 61ae41f198 | |||
| a3d9c39c06 | |||
| 02690f7583 | |||
| ddfcc6a60b | |||
| 148ea89bbf | |||
| 616c4c26e0 | |||
| 073391f7d6 | |||
| be5c67d4b1 | |||
| 9b7228c544 | |||
| 2d933590cf | |||
| c0ae51dfe4 | |||
| 9afa7bc92c | |||
| e5adaef980 | |||
| 73eb3a9d22 | |||
| 6dd055d2eb | |||
| 5eb75e211e | |||
| ca62bee964 | |||
| fa839dcac0 | |||
| 09ffa773dd | |||
| 83a9a264be | |||
| 8209a7c535 | |||
| 2baccac82f | |||
| 79d18bc4dd | |||
| 05821b0ee3 | |||
| 8a3a2a99b2 | |||
| d1c89cd7e9 | |||
| 8ee0d14795 | |||
| 2b2676f698 | |||
| 5c38c05b26 | |||
| 493b2a4bf8 | |||
| 1ac76f7ed0 | |||
| eb599890b9 | |||
| 9abf84cc82 | |||
| b387e229a9 | |||
| 0fcac4bf99 | |||
| 58e449904e | |||
| b8a3550f0f | |||
| 61e8d36f84 | |||
| 0c292edb90 | |||
| 7ed2e82e5a | |||
| 90801c125a | |||
| 29975899e3 | |||
| aaa4045b04 | |||
| 7c12587994 | |||
| c1399186bf | |||
| c88f24596c | |||
| def85b403d | |||
| 075875fbf6 | |||
| 91871018a4 | |||
| a5237972fa | |||
| a684152a2f | |||
| 0d5bf8d86d | |||
| a0cb725b39 | |||
| fb383f0c3d | |||
| afd88c27f2 | |||
| d617e01cfa | |||
| 321fcdc458 | |||
| e11726a9a4 | |||
| a365138ac6 | |||
| 01d65c27ec | |||
| 7d53128d35 | |||
| 2c1523733a | |||
| f131301413 | |||
| 8da870a9e0 | |||
| 02ba1789a3 | |||
| 1997ef22d7 | |||
| 1d134eee9a | |||
| b1ffe0b36a | |||
| 7ce349ef26 | |||
| 8ebc9eafec | |||
| c86a230089 | |||
| 08c9b84410 | |||
| 518ba0772b | |||
| 947417a159 | |||
| b0d864ee6d | |||
| c2dce9c1d5 | |||
| 11f11e6f49 | |||
| 7784104dd8 | |||
| f3d3cee4fe | |||
| 23ebe09eab | |||
| 6c679e1b3b | |||
| fc674c82c3 | |||
| 778e5cedf0 | |||
| 3975ecffc2 | |||
| 34a8aacb51 | |||
| 0648129566 | |||
| a54ebffa76 | |||
| 4b65693c7e | |||
| 44d40c5e2b | |||
| 696b6b50b0 | |||
| 30bcb3bd28 | |||
| 1bd689d1fc | |||
| e2a701ea1e | |||
| e5be1740be | |||
| 13a129d301 | |||
| 777fdd6443 | |||
| 378a08aa31 | |||
| 6fdea2aba9 | |||
| de254b4c4e | |||
| 5b6151df1d | |||
| 97104afe9e | |||
| fc9f10f8fb | |||
| 6c7f6bfa97 | |||
| fb83bc32ae | |||
| 2c45fa0b90 | |||
| 76dd18008c | |||
| 1ddd6e5365 | |||
| 8c62d9dd8b | |||
| 536036abf4 | |||
| d075706ea5 | |||
| 71c21b4300 | |||
| 96bc12a494 | |||
| 783e095787 | |||
| bc6a76b0e0 | |||
| 90ada2f4ec | |||
| bc7daec4d8 | |||
| 92f888e836 | |||
| 88bb8489db | |||
| 730d69e159 | |||
| 11fa70396b | |||
| a33e0fc932 | |||
| 2c673f15f6 | |||
| 61c4e27413 | |||
| d7bc3353f0 | |||
| b15143fece | |||
| 400d0b7b5e | |||
| 89abf7a466 | |||
| a0eb4a8193 | |||
| 82b2b8574f | |||
| fb8b763e51 | |||
| 82bad05d5d | |||
| 23aff6b094 | |||
| d403be92a4 | |||
| b7ded430e4 | |||
| ddd5ba78a9 | |||
| f004aa556d | |||
| d0b988219f | |||
| 31fa5a446a | |||
| 7e06de5d2d | |||
| cb3af3e9c1 | |||
| a53344972b | |||
| 4a2cc28b8c | |||
| 43780cbc37 | |||
| 20422539b5 | |||
| f55e2e7266 | |||
| 3cfeb9522b | |||
| c196680120 | |||
| bbba9394c8 | |||
| d9e5bc1013 | |||
| ebacdeed67 | |||
| d3bca049ee | |||
| adc15a79ad | |||
| ab0e20a97d | |||
| 10f6bc7fd0 | |||
| aff72a3805 | |||
| 7182d51fb9 | |||
| 2065481c40 | |||
| d0a4059102 | |||
| 7f26bf8421 | |||
| 323f1eb701 | |||
| fd49993c3b | |||
| 0ef8c7bd8f | |||
| 1d2c02bb8e | |||
| 69522117a6 | |||
| 0aef1686de | |||
| d69d94e7e3 | |||
| 4e78e30933 | |||
| d768c5d767 | |||
| e1d18a7a88 | |||
| 417830d981 | |||
| 05bb1c5033 | |||
| cc17c24852 | |||
| 6114c3c5d4 | |||
| a232a7159c | |||
| bf833c346d | |||
| 76feb1f97f | |||
| 7c83fdaf5b | |||
| 712f372489 | |||
| 3e0b2ce12b | |||
| c8ff30cbe7 | |||
| 0686c09eea | |||
| b18cb6a5d0 | |||
| 42329a828b | |||
| 8b487b73aa | |||
| 67bb45f44b | |||
| faa539f877 | |||
| ebcb5beb19 | |||
| 107d4388cb | |||
| cbfd3c044c | |||
| 0c05c37f93 | |||
| 519118f984 | |||
| a5f1b38de5 | |||
| 7e9949c30b | |||
| 17eeb9820c | |||
| 6bb507bc9c | |||
| e94ec3f85b | |||
| 79bc7a3212 | |||
| 643b77e644 | |||
| 053a8f728e | |||
| 8d979e5430 | |||
| b0ad3d74db | |||
| 43ea204db7 | |||
| d1c0de6fe0 | |||
| f368c73826 | |||
| fef78b0356 | |||
| a507617e4d | |||
| 764ab9802e | |||
| a0ba400c33 | |||
| ccbb165d98 | |||
| 8c26d750e1 | |||
| 7a60ca095d | |||
| 0f5d7d3f04 | |||
| 95321e15f2 | |||
| bbfe603519 | |||
| fc2d78dd1e | |||
| 681eb6ac2d | |||
| 32c8927159 | |||
| 81a191dc4d | |||
| 94cf5d030f | |||
| e000440982 | |||
| ca307ab6a3 | |||
| 065d733c4b | |||
| 2a0707210a | |||
| 246eeee61a | |||
| 794cc59e25 | |||
| 02084ea398 | |||
| 3cb12467cc | |||
| 7ce10d5da7 | |||
| 4784b99bf3 | |||
| 7d2dbc3791 | |||
| e3843d41b9 | |||
| f466cdb5e0 | |||
| bbf4246546 | |||
| 8cd7bbf514 | |||
| 3cb047e56c | |||
| 2d85062c4f | |||
| f35e8384a8 | |||
| 7179e53ea6 | |||
| 1d4fa785bc | |||
| cfb9d147bb | |||
| c90ed1901d | |||
| 96e744c176 | |||
| 9292632c8d | |||
| 5e2d0c929c | |||
| 57e81e666a | |||
| cedc6f1824 | |||
| d851842228 | |||
| aea20c15c9 | |||
| 5c12778948 | |||
| 2d05568a7b | |||
| fd67f61bb4 | |||
| 5916207dd3 | |||
| 8c6467976c | |||
| eb3028847e | |||
| 2ddc461a3f | |||
| 6a53b99f34 | |||
| 076c6a3389 | |||
| aefc6b27e1 | |||
| b228541129 | |||
| 73812e06b0 | |||
| edb729959f | |||
| 3c8652d0c6 | |||
| 438229a8d7 | |||
| 48e1d180a4 | |||
| 2070f8ad91 | |||
| 707af294a8 | |||
| 4c341d0299 | |||
| be49706c42 | |||
| 93103177a5 | |||
| 91222b8d38 | |||
| 6ad20dc912 | |||
| 130d529b71 | |||
| d04ca95356 | |||
| c77ea04c81 | |||
| 35ac5b7500 | |||
| fe36672bf5 | |||
| 0cade989e7 | |||
| b6473199a3 | |||
| 54689ed91e | |||
| ab1d28e305 | |||
| 8ebeabf0e2 | |||
| f29c429324 | |||
| f465461062 | |||
| 924a352d1b | |||
| 9ea9f9ce51 | |||
| d6c22ee938 | |||
| 919d8cf94e | |||
| 84cd49385c | |||
| a58baaf9e6 | |||
| ad8f5e1de9 | |||
| 7dd4e429a5 | |||
| 11c82895d7 | |||
| 7e42999122 | |||
| 39425b0f36 | |||
| d5c565a98d | |||
| 94a62e61aa | |||
| 2a3b3439c8 | |||
| 415c010d4a | |||
| 0bdef09263 | |||
| 34b4c829fd | |||
| 2ff7933f22 | |||
| 0d3c96337a | |||
| 591f251bf3 | |||
| ba9557d0ef | |||
| 218f51bcef | |||
| 898be92b67 |
@@ -14,8 +14,11 @@ util/bot/cmake-win32
|
||||
util/bot/cmake-win32.zip
|
||||
util/bot/golang
|
||||
util/bot/gyp
|
||||
util/bot/libFuzzer
|
||||
util/bot/llvm-build
|
||||
util/bot/perl-win32
|
||||
util/bot/perl-win32.zip
|
||||
util/bot/sde-linux64
|
||||
util/bot/sde-linux64.tar.bz2
|
||||
util/bot/win_toolchain.json
|
||||
util/bot/yasm-win32.exe
|
||||
|
||||
+20
-9
@@ -33,7 +33,7 @@
|
||||
executable may be configured explicitly by setting `GO_EXECUTABLE`.
|
||||
|
||||
* To build the x86 and x86\_64 assembly, your assembler must support AVX2
|
||||
instructions and MOVBE. If using GNU binutils, you must have 2.22 or later.
|
||||
instructions and MOVBE. If using GNU binutils, you must have 2.22 or later
|
||||
|
||||
## Building
|
||||
|
||||
@@ -96,6 +96,15 @@ higher to build aarch64 binaries.
|
||||
|
||||
For other options, see [android-cmake's documentation](./third_party/android-cmake/README.md).
|
||||
|
||||
### Building for iOS
|
||||
|
||||
To build for iOS, pass `-DCMAKE_OSX_SYSROOT=iphoneos` and
|
||||
`-DCMAKE_OSX_ARCHITECTURES=ARCH` to CMake, where `ARCH` is the desired
|
||||
architecture, matching values used in the `-arch` flag in Apple's toolchain.
|
||||
|
||||
Passing multiple architectures for a multiple-architecture build is not
|
||||
supported.
|
||||
|
||||
## Known Limitations on Windows
|
||||
|
||||
* Versions of CMake since 3.0.2 have a bug in its Ninja generator that causes
|
||||
@@ -116,16 +125,18 @@ ARM, unlike Intel, does not have an instruction that allows applications to
|
||||
discover the capabilities of the processor. Instead, the capability information
|
||||
has to be provided by the operating system somehow.
|
||||
|
||||
BoringSSL will try to use `getauxval` to discover the capabilities and, failing
|
||||
that, will probe for NEON support by executing a NEON instruction and handling
|
||||
any illegal-instruction signal. But some environments don't support that sort
|
||||
of thing and, for them, it's possible to configure the CPU capabilities
|
||||
at compile time.
|
||||
By default, on Linux-based systems, BoringSSL will try to use `getauxval` and
|
||||
`/proc` to discover the capabilities. But some environments don't support that
|
||||
sort of thing and, for them, it's possible to configure the CPU capabilities at
|
||||
compile time.
|
||||
|
||||
If you define `OPENSSL_STATIC_ARMCAP` then you can define any of the following
|
||||
to enabling the corresponding ARM feature.
|
||||
On iOS or builds which define `OPENSSL_STATIC_ARMCAP`, features will be
|
||||
determined based on the `__ARM_NEON__` and `__ARM_FEATURE_CRYPTO` preprocessor
|
||||
symbols reported by the compiler. These values are usually controlled by the
|
||||
`-march` flag. You can also define any of the following to enable the
|
||||
corresponding ARM feature.
|
||||
|
||||
* `OPENSSL_STATIC_ARMCAP_NEON` or `__ARM_NEON__` (note that the latter is set by compilers when NEON support is enabled).
|
||||
* `OPENSSL_STATIC_ARMCAP_NEON`
|
||||
* `OPENSSL_STATIC_ARMCAP_AES`
|
||||
* `OPENSSL_STATIC_ARMCAP_SHA1`
|
||||
* `OPENSSL_STATIC_ARMCAP_SHA256`
|
||||
|
||||
+114
-44
@@ -9,6 +9,8 @@ if(WIN32)
|
||||
set(CMAKE_GENERATOR_CC cl)
|
||||
endif()
|
||||
|
||||
include(sources.cmake)
|
||||
|
||||
enable_language(C)
|
||||
enable_language(CXX)
|
||||
|
||||
@@ -30,16 +32,35 @@ if (NOT GO_EXECUTABLE)
|
||||
message(FATAL_ERROR "Could not find Go")
|
||||
endif()
|
||||
|
||||
if (BORINGSSL_ALLOW_CXX_RUNTIME)
|
||||
add_definitions(-DBORINGSSL_ALLOW_CXX_RUNTIME)
|
||||
endif()
|
||||
|
||||
if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||
set(C_CXX_FLAGS "-Wall -Werror -Wformat=2 -Wsign-compare -Wmissing-field-initializers -Wwrite-strings -ggdb -fvisibility=hidden -fno-common")
|
||||
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||
set(C_CXX_FLAGS "${C_CXX_FLAGS} -Wnewline-eof")
|
||||
set(C_CXX_FLAGS "${C_CXX_FLAGS} -Wnewline-eof -fcolor-diagnostics")
|
||||
else()
|
||||
# GCC (at least 4.8.4) has a bug where it'll find unreachable free() calls
|
||||
# and declare that the code is trying to free a stack pointer.
|
||||
set(C_CXX_FLAGS "${C_CXX_FLAGS} -Wno-free-nonheap-object")
|
||||
endif()
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${C_CXX_FLAGS} -Wmissing-prototypes -Wold-style-definition -Wstrict-prototypes")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 ${C_CXX_FLAGS} -Wmissing-declarations")
|
||||
# Clang's integerated assembler does not support debug symbols.
|
||||
if(NOT CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||
set(CMAKE_ASM_FLAGS "${CMAKE_ASM_FLAGS} -Wa,-g")
|
||||
|
||||
if(NOT BORINGSSL_ALLOW_CXX_RUNTIME)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-exceptions -fno-rtti")
|
||||
endif()
|
||||
|
||||
# In GCC, -Wmissing-declarations is the C++ spelling of -Wmissing-prototypes
|
||||
# and using the wrong one is an error. In Clang, -Wmissing-prototypes is the
|
||||
# spelling for both and -Wmissing-declarations is some other warning.
|
||||
#
|
||||
# https://gcc.gnu.org/onlinedocs/gcc-7.1.0/gcc/Warning-Options.html#Warning-Options
|
||||
# https://clang.llvm.org/docs/DiagnosticsReference.html#wmissing-prototypes
|
||||
# https://clang.llvm.org/docs/DiagnosticsReference.html#wmissing-declarations
|
||||
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wmissing-prototypes -Wimplicit-fallthrough")
|
||||
endif()
|
||||
elseif(MSVC)
|
||||
set(MSVC_DISABLED_WARNINGS_LIST
|
||||
@@ -104,10 +125,16 @@ elseif(MSVC)
|
||||
set(CMAKE_C_FLAGS "-Wall -WX ${MSVC_DISABLED_WARNINGS_STR} ${MSVC_LEVEL4_WARNINGS_STR}")
|
||||
set(CMAKE_CXX_FLAGS "-Wall -WX ${MSVC_DISABLED_WARNINGS_STR} ${MSVC_LEVEL4_WARNINGS_STR}")
|
||||
set(CMAKE_ASM_NASM_FLAGS "-g cv8")
|
||||
endif()
|
||||
|
||||
if(WIN32)
|
||||
add_definitions(-D_HAS_EXCEPTIONS=0)
|
||||
add_definitions(-DWIN32_LEAN_AND_MEAN)
|
||||
add_definitions(-DNOMINMAX)
|
||||
add_definitions(-D_CRT_SECURE_NO_WARNINGS) # Allow use of fopen
|
||||
# Allow use of fopen.
|
||||
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
|
||||
# VS 2017 and higher supports STL-only warning suppressions.
|
||||
add_definitions("-D_STL_EXTRA_DISABLED_WARNINGS=4774 4987")
|
||||
endif()
|
||||
|
||||
if((CMAKE_COMPILER_IS_GNUCXX AND CMAKE_C_COMPILER_VERSION VERSION_GREATER "4.7.99") OR
|
||||
@@ -143,8 +170,8 @@ if(FUZZ)
|
||||
set(RUNNER_ARGS ${RUNNER_ARGS} "-fuzzer" "-shim-config" "fuzzer_mode.json")
|
||||
endif()
|
||||
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address -fsanitize-coverage=edge,indirect-calls,8bit-counters")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fsanitize-coverage=edge,indirect-calls,8bit-counters")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address -fsanitize-coverage=edge,indirect-calls,trace-pc-guard")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fsanitize-coverage=edge,indirect-calls,trace-pc-guard")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address")
|
||||
link_directories(.)
|
||||
endif()
|
||||
@@ -158,7 +185,64 @@ if (BUILD_SHARED_LIBS)
|
||||
set(CMAKE_POSITION_INDEPENDENT_CODE TRUE)
|
||||
endif()
|
||||
|
||||
if (${CMAKE_SYSTEM_PROCESSOR} STREQUAL "x86_64")
|
||||
if (MSAN)
|
||||
if(NOT CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||
message(FATAL_ERROR "Cannot enable MSAN unless using Clang")
|
||||
endif()
|
||||
|
||||
if (ASAN)
|
||||
message(FATAL_ERROR "ASAN and MSAN are mutually exclusive")
|
||||
endif()
|
||||
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=memory -fsanitize-memory-track-origins -fno-omit-frame-pointer")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=memory -fsanitize-memory-track-origins -fno-omit-frame-pointer")
|
||||
set(OPENSSL_NO_ASM "1")
|
||||
endif()
|
||||
|
||||
if (ASAN)
|
||||
if(NOT CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||
message(FATAL_ERROR "Cannot enable ASAN unless using Clang")
|
||||
endif()
|
||||
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address -fsanitize-address-use-after-scope -fno-omit-frame-pointer")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fsanitize-address-use-after-scope -fno-omit-frame-pointer")
|
||||
set(OPENSSL_NO_ASM "1")
|
||||
endif()
|
||||
|
||||
if (GCOV)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fprofile-arcs -ftest-coverage")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage")
|
||||
endif()
|
||||
|
||||
if(FIPS)
|
||||
add_definitions(-DBORINGSSL_FIPS)
|
||||
if(FIPS_BREAK_TEST)
|
||||
add_definitions("-DBORINGSSL_FIPS_BREAK_${FIPS_BREAK_TEST}=1")
|
||||
endif()
|
||||
# Delocate does not work for ASan and MSan builds.
|
||||
if(NOT ASAN AND NOT MSAN)
|
||||
set(FIPS_DELOCATE "1")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# CMake's iOS support uses Apple's multiple-architecture toolchain. It takes an
|
||||
# architecture list from CMAKE_OSX_ARCHITECTURES, leaves CMAKE_SYSTEM_PROCESSOR
|
||||
# alone, and expects all architecture-specific logic to be conditioned within
|
||||
# the source files rather than the build. This does not work for our assembly
|
||||
# files, so we fix CMAKE_SYSTEM_PROCESSOR and only support single-architecture
|
||||
# builds.
|
||||
if (NOT OPENSSL_NO_ASM AND CMAKE_OSX_ARCHITECTURES)
|
||||
list(LENGTH CMAKE_OSX_ARCHITECTURES NUM_ARCHES)
|
||||
if (NOT ${NUM_ARCHES} EQUAL 1)
|
||||
message(FATAL_ERROR "Universal binaries not supported.")
|
||||
endif()
|
||||
list(GET CMAKE_OSX_ARCHITECTURES 0 CMAKE_SYSTEM_PROCESSOR)
|
||||
endif()
|
||||
|
||||
if (OPENSSL_NO_ASM)
|
||||
add_definitions(-DOPENSSL_NO_ASM)
|
||||
set(ARCH "generic")
|
||||
elseif (${CMAKE_SYSTEM_PROCESSOR} STREQUAL "x86_64")
|
||||
set(ARCH "x86_64")
|
||||
elseif (${CMAKE_SYSTEM_PROCESSOR} STREQUAL "amd64")
|
||||
set(ARCH "x86_64")
|
||||
@@ -175,10 +259,12 @@ elseif (${CMAKE_SYSTEM_PROCESSOR} STREQUAL "i386")
|
||||
set(ARCH "x86")
|
||||
elseif (${CMAKE_SYSTEM_PROCESSOR} STREQUAL "i686")
|
||||
set(ARCH "x86")
|
||||
elseif (${CMAKE_SYSTEM_PROCESSOR} MATCHES "^arm*")
|
||||
set(ARCH "arm")
|
||||
elseif (${CMAKE_SYSTEM_PROCESSOR} STREQUAL "aarch64")
|
||||
set(ARCH "aarch64")
|
||||
elseif (${CMAKE_SYSTEM_PROCESSOR} STREQUAL "arm64")
|
||||
set(ARCH "aarch64")
|
||||
elseif (${CMAKE_SYSTEM_PROCESSOR} MATCHES "^arm*")
|
||||
set(ARCH "arm")
|
||||
elseif (${CMAKE_SYSTEM_PROCESSOR} STREQUAL "mips")
|
||||
# Just to avoid the “unknown processor” error.
|
||||
set(ARCH "generic")
|
||||
@@ -202,40 +288,6 @@ if (${ARCH} STREQUAL "x86" AND APPLE)
|
||||
set(ARCH "x86_64")
|
||||
endif()
|
||||
|
||||
if (MSAN)
|
||||
if(NOT CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||
message(FATAL_ERROR "Cannot enable MSAN unless using Clang")
|
||||
endif()
|
||||
|
||||
if (ASAN)
|
||||
message(FATAL_ERROR "ASAN and MSAN are mutually exclusive")
|
||||
endif()
|
||||
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=memory -fsanitize-memory-track-origins -fno-omit-frame-pointer")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=memory -fsanitize-memory-track-origins -fno-omit-frame-pointer")
|
||||
set(OPENSSL_NO_ASM "1")
|
||||
endif()
|
||||
|
||||
if (ASAN)
|
||||
if(NOT CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||
message(FATAL_ERROR "Cannot enable ASAN unless using Clang")
|
||||
endif()
|
||||
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address -fno-omit-frame-pointer")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fno-omit-frame-pointer")
|
||||
set(OPENSSL_NO_ASM "1")
|
||||
endif()
|
||||
|
||||
if (GCOV)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fprofile-arcs -ftest-coverage")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage")
|
||||
endif()
|
||||
|
||||
if (OPENSSL_NO_ASM)
|
||||
add_definitions(-DOPENSSL_NO_ASM)
|
||||
set(ARCH "generic")
|
||||
endif()
|
||||
|
||||
# Add minimal googletest targets. The provided one has many side-effects, and
|
||||
# googletest has a very straightforward build.
|
||||
add_library(gtest third_party/googletest/src/gtest-all.cc)
|
||||
@@ -247,13 +299,31 @@ include_directories(third_party/googletest/include)
|
||||
# themselves as dependencies next to the target definition.
|
||||
add_custom_target(all_tests)
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT crypto_test_data.cc
|
||||
COMMAND ${GO_EXECUTABLE} run util/embed_test_data.go ${CRYPTO_TEST_DATA} >
|
||||
${CMAKE_CURRENT_BINARY_DIR}/crypto_test_data.cc
|
||||
DEPENDS util/embed_test_data.go ${CRYPTO_TEST_DATA}
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
||||
add_library(crypto_test_data OBJECT crypto_test_data.cc)
|
||||
|
||||
add_subdirectory(crypto)
|
||||
add_subdirectory(ssl)
|
||||
add_subdirectory(ssl/test)
|
||||
add_subdirectory(fipstools)
|
||||
add_subdirectory(tool)
|
||||
add_subdirectory(decrepit)
|
||||
|
||||
if(FUZZ)
|
||||
if(LIBFUZZER_FROM_DEPS)
|
||||
file(GLOB LIBFUZZER_SOURCES "util/bot/libFuzzer/*.cpp")
|
||||
add_library(Fuzzer STATIC ${LIBFUZZER_SOURCES})
|
||||
# libFuzzer does not pass our aggressive warnings. It also must be built
|
||||
# without -fsanitize-coverage options or clang crashes.
|
||||
set_target_properties(Fuzzer PROPERTIES COMPILE_FLAGS "-Wno-shadow -Wno-format-nonliteral -Wno-missing-prototypes -fsanitize-coverage=0")
|
||||
endif()
|
||||
|
||||
add_subdirectory(fuzz)
|
||||
endif()
|
||||
|
||||
|
||||
+4
-2
@@ -68,17 +68,19 @@ Additionally, if `BORINGSSL_UNSAFE_FUZZER_MODE` is set, BoringSSL will:
|
||||
|
||||
* Tickets are unencrypted and the MAC check is performed but ignored.
|
||||
|
||||
* renegotiation\_info checks are ignored.
|
||||
|
||||
This is to prevent the fuzzer from getting stuck at a cryptographic invariant in the protocol.
|
||||
|
||||
## TLS transcripts
|
||||
|
||||
The `client` and `server` corpora are seeded from the test suite. The test suite has a `-fuzzer` flag which mirrors the fuzzer mode changes above and a `-deterministic` flag which removes all non-determinism on the Go side. Not all tests pass, so `ssl/test/runner/fuzzer_mode.json` contains the necessary suppressions. The `run_tests` target will pass appropriate command-line flags.
|
||||
|
||||
There are separate corpora, `client_corpus_no_fuzzer_mode` and `server_corpus_no_fuzzer_mode`. These are transcripts for fuzzers with only `BORINGSSL_UNSAFE_DETERMINISTIC_MODE` defined. To build in this mode, pass `-DNO_FUZZER_MODE=1` into CMake. This configuration is run in the same way but without `-fuzzer` and `-shim-path` flags.
|
||||
There are separate corpora, `client_corpus_no_fuzzer_mode` and `server_corpus_no_fuzzer_mode`. These are transcripts for fuzzers with only `BORINGSSL_UNSAFE_DETERMINISTIC_MODE` defined. To build in this mode, pass `-DNO_FUZZER_MODE=1` into CMake. This configuration is run in the same way but without `-fuzzer` and `-shim-config` flags.
|
||||
|
||||
If both sets of tests pass, refresh the fuzzer corpora with `refresh_ssl_corpora.sh`:
|
||||
|
||||
```
|
||||
cd fuzz
|
||||
./refresh_fuzzer_corpora.sh /path/to/fuzzer/mode/build /path/to/non/fuzzer/mode/build
|
||||
./refresh_ssl_corpora.sh /path/to/fuzzer/mode/build /path/to/non/fuzzer/mode/build
|
||||
```
|
||||
|
||||
+39
-1
@@ -116,7 +116,9 @@ response in (unpipelined) HTTP/1.1.
|
||||
|
||||
Things which do not work:
|
||||
|
||||
* There is no support for renegotiation as a server.
|
||||
* There is no support for renegotiation as a server. (Attempts by clients will
|
||||
result in a fatal alert so that ClientHello messages cannot be used to flood
|
||||
a server and escape higher-level limits.)
|
||||
|
||||
* There is no support for renegotiation in DTLS.
|
||||
|
||||
@@ -128,6 +130,17 @@ Things which do not work:
|
||||
* If a HelloRequest is received while `SSL_write` has unsent application data,
|
||||
the renegotiation is rejected.
|
||||
|
||||
* Renegotiation does not participate in session resumption. The client will
|
||||
not offer a session on renegotiation or resume any session established by a
|
||||
renegotiation handshake.
|
||||
|
||||
* The server may not change its certificate in the renegotiation. This mitigates
|
||||
the [triple handshake attack](https://mitls.org/pages/attacks/3SHAKE). Any new
|
||||
stapled OCSP response and SCT list will be ignored. As no authentication state
|
||||
may change, BoringSSL will not re-verify the certificate on a renegotiation.
|
||||
Callbacks such as `SSL_CTX_set_custom_verify` will only run on the initial
|
||||
handshake.
|
||||
|
||||
### Lowercase hexadecimal
|
||||
|
||||
BoringSSL's `BN_bn2hex` function uses lowercase hexadecimal digits instead of
|
||||
@@ -227,6 +240,7 @@ parameter.
|
||||
`SSL_CTRL_OPTIONS` | `SSL_CTX_get_options` or `SSL_CTX_set_options`
|
||||
`SSL_CTRL_SESS_NUMBER` | `SSL_CTX_sess_number`
|
||||
`SSL_CTRL_SET_CURVES` | `SSL_CTX_set1_curves`
|
||||
`SSL_CTRL_SET_ECDH_AUTO` | `SSL_CTX_set_ecdh_auto`
|
||||
`SSL_CTRL_SET_MAX_CERT_LIST` | `SSL_CTX_set_max_cert_list`
|
||||
`SSL_CTRL_SET_MAX_SEND_FRAGMENT` | `SSL_CTX_set_max_send_fragment`
|
||||
`SSL_CTRL_SET_MSG_CALLBACK` | `SSL_set_msg_callback`
|
||||
@@ -246,3 +260,27 @@ parameter.
|
||||
`SSL_CTRL_SET_TMP_ECDH_CB` | `SSL_CTX_set_tmp_ecdh_callback`
|
||||
`SSL_CTRL_SET_TMP_RSA` | `SSL_CTX_set_tmp_rsa` is equivalent, but [*do not use this function*](https://freakattack.com/). (It is a no-op in BoringSSL.)
|
||||
`SSL_CTRL_SET_TMP_RSA_CB` | `SSL_CTX_set_tmp_rsa_callback` is equivalent, but [*do not use this function*](https://freakattack.com/). (It is a no-op in BoringSSL.)
|
||||
|
||||
## Significant API additions
|
||||
|
||||
In some places, BoringSSL has added significant APIs. Use of these APIs goes beyound “porting” and means giving up on OpenSSL compatibility.
|
||||
|
||||
One example of this has already been mentioned: the [CBS and CBB](https://commondatastorage.googleapis.com/chromium-boringssl-docs/bytestring.h.html) functions should be used whenever parsing or serialising data.
|
||||
|
||||
### CRYPTO\_BUFFER
|
||||
|
||||
With the standard OpenSSL APIs, when making many TLS connections, the certificate data for each connection is retained in memory in an expensive `X509` structure. Additionally, common certificates often appear in the chains for multiple connections and are needlessly duplicated in memory.
|
||||
|
||||
A [`CRYPTO_BUFFER`](https://commondatastorage.googleapis.com/chromium-boringssl-docs/pool.h.html) is just an opaque byte string. A `CRYPTO_BUFFER_POOL` is an intern table for these buffers, i.e. it ensures that only a single copy of any given byte string is kept for each pool.
|
||||
|
||||
The function `TLS_with_buffers_method` returns an `SSL_METHOD` that avoids creating `X509` objects for certificates. Additionally, `SSL_CTX_set0_buffer_pool` can be used to install a pool on an `SSL_CTX` so that certificates can be deduplicated across connections and across `SSL_CTX`s.
|
||||
|
||||
When using these functions, the application also needs to ensure that it doesn't call other functions that deal with `X509` or `X509_NAME` objects. For example, `SSL_get_peer_certificate` or `SSL_get_peer_cert_chain`. Doing so will trigger an assert in debug mode and will result in NULLs in release mode. Instead, call the buffer-based alternatives such as `SSL_get0_peer_certificates`. (See [ssl.h](https://commondatastorage.googleapis.com/chromium-boringssl-docs/ssl.h.html) for functions taking or returning `CRYPTO_BUFFER`.) The buffer-based alternative functions will work even when not using `TLS_with_buffers_method`, thus application code can transition gradually.
|
||||
|
||||
In order to use buffers, the application code also needs to implement its own certificate verification using `SSL_[CTX_]set_custom_verify`. Otherwise all connections will fail with a verification error. Auto-chaining is also disabled when using buffers.
|
||||
|
||||
Once those changes have been completed, the whole of the OpenSSL X.509 and ASN.1 code should be eliminated by the linker if BoringSSL is linked statically.
|
||||
|
||||
### Asynchronous and opaque private keys
|
||||
|
||||
OpenSSL offers the ENGINE API for implementing opaque private keys (i.e. private keys where software only has oracle access because the secrets are held in special hardware or on another machine). While the ENGINE API has been mostly removed from BoringSSL, it is still possible to support opaque keys in this way. However, when using such keys with TLS and BoringSSL, you should strongly prefer using `SSL_PRIVATE_KEY_METHOD` via `SSL[_CTX]_set_private_key_method`. This allows a handshake to be suspended while the private operation is in progress. It also supports more forms of opaque key as it exposes higher-level information about the operation to be performed.
|
||||
|
||||
@@ -207,3 +207,14 @@ return value patterns in legacy functions.
|
||||
|
||||
Document private functions in their `internal.h` header or, if static,
|
||||
where defined.
|
||||
|
||||
|
||||
## Build logic
|
||||
|
||||
BoringSSL is used by many projects with many different build tools.
|
||||
Reimplementing and maintaining build logic in each downstream build is
|
||||
cumbersome, so build logic should be avoided where possible. Platform-specific
|
||||
files should be excluded by wrapping the contents in `#ifdef`s, rather than
|
||||
computing platform-specific file lists. Generated source files such as perlasm
|
||||
and `err_data.c` may be used in the standalone CMake build but, for downstream
|
||||
builds, they should be pre-generated in `generate_build_files.py`.
|
||||
|
||||
+148
-99
@@ -1,43 +1,63 @@
|
||||
include_directories(../include)
|
||||
|
||||
if(APPLE)
|
||||
if (${ARCH} STREQUAL "x86")
|
||||
set(PERLASM_FLAGS "-fPIC -DOPENSSL_IA32_SSE2")
|
||||
endif()
|
||||
set(PERLASM_STYLE macosx)
|
||||
set(ASM_EXT S)
|
||||
enable_language(ASM)
|
||||
elseif(UNIX)
|
||||
if (${ARCH} STREQUAL "aarch64")
|
||||
# The "armx" Perl scripts look for "64" in the style argument
|
||||
# in order to decide whether to generate 32- or 64-bit asm.
|
||||
set(PERLASM_STYLE linux64)
|
||||
elseif (${ARCH} STREQUAL "arm")
|
||||
set(PERLASM_STYLE linux32)
|
||||
elseif (${ARCH} STREQUAL "x86")
|
||||
set(PERLASM_FLAGS "-fPIC -DOPENSSL_IA32_SSE2")
|
||||
set(PERLASM_STYLE elf)
|
||||
elseif (${ARCH} STREQUAL "ppc64le")
|
||||
set(PERLASM_STYLE ppc64le)
|
||||
else()
|
||||
set(PERLASM_STYLE elf)
|
||||
endif()
|
||||
set(ASM_EXT S)
|
||||
enable_language(ASM)
|
||||
set(CMAKE_ASM_FLAGS "${CMAKE_ASM_FLAGS} -Wa,--noexecstack")
|
||||
else()
|
||||
if (CMAKE_CL_64)
|
||||
message("Using nasm")
|
||||
set(PERLASM_STYLE nasm)
|
||||
else()
|
||||
message("Using win32n")
|
||||
set(PERLASM_STYLE win32n)
|
||||
set(PERLASM_FLAGS "-DOPENSSL_IA32_SSE2")
|
||||
endif()
|
||||
if(NOT OPENSSL_NO_ASM)
|
||||
if(UNIX)
|
||||
if (${ARCH} STREQUAL "aarch64")
|
||||
# The "armx" Perl scripts look for "64" in the style argument
|
||||
# in order to decide whether to generate 32- or 64-bit asm.
|
||||
if (APPLE)
|
||||
set(PERLASM_STYLE ios64)
|
||||
else()
|
||||
set(PERLASM_STYLE linux64)
|
||||
endif()
|
||||
elseif (${ARCH} STREQUAL "arm")
|
||||
if (APPLE)
|
||||
set(PERLASM_STYLE ios32)
|
||||
else()
|
||||
set(PERLASM_STYLE linux32)
|
||||
endif()
|
||||
elseif (${ARCH} STREQUAL "ppc64le")
|
||||
set(PERLASM_STYLE linux64le)
|
||||
else()
|
||||
if (${ARCH} STREQUAL "x86")
|
||||
set(PERLASM_FLAGS "-fPIC -DOPENSSL_IA32_SSE2")
|
||||
endif()
|
||||
if (APPLE)
|
||||
set(PERLASM_STYLE macosx)
|
||||
else()
|
||||
set(PERLASM_STYLE elf)
|
||||
endif()
|
||||
endif()
|
||||
set(ASM_EXT S)
|
||||
enable_language(ASM)
|
||||
set(CMAKE_ASM_FLAGS "${CMAKE_ASM_FLAGS} -Wa,--noexecstack")
|
||||
|
||||
# On Windows, we use the NASM output, specifically built with Yasm.
|
||||
set(ASM_EXT asm)
|
||||
enable_language(ASM_NASM)
|
||||
# Clang's integerated assembler does not support debug symbols.
|
||||
if(NOT CMAKE_ASM_COMPILER_ID MATCHES "Clang")
|
||||
set(CMAKE_ASM_FLAGS "${CMAKE_ASM_FLAGS} -Wa,-g")
|
||||
endif()
|
||||
|
||||
# CMake does not add -isysroot and -arch flags to assembly.
|
||||
if (APPLE)
|
||||
if (CMAKE_OSX_SYSROOT)
|
||||
set(CMAKE_ASM_FLAGS "${CMAKE_ASM_FLAGS} -isysroot ${CMAKE_OSX_SYSROOT}")
|
||||
endif()
|
||||
foreach(arch ${CMAKE_OSX_ARCHITECTURES})
|
||||
set(CMAKE_ASM_FLAGS "${CMAKE_ASM_FLAGS} -arch ${arch}")
|
||||
endforeach()
|
||||
endif()
|
||||
else()
|
||||
if (${ARCH} STREQUAL "x86_64")
|
||||
set(PERLASM_STYLE nasm)
|
||||
else()
|
||||
set(PERLASM_STYLE win32n)
|
||||
set(PERLASM_FLAGS "-DOPENSSL_IA32_SSE2")
|
||||
endif()
|
||||
|
||||
# On Windows, we use the NASM output, specifically built with Yasm.
|
||||
set(ASM_EXT asm)
|
||||
enable_language(ASM_NASM)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
function(perlasm dest src)
|
||||
@@ -67,12 +87,6 @@ add_subdirectory(bytestring)
|
||||
add_subdirectory(pool)
|
||||
|
||||
# Level 0.2 - depends on nothing but itself
|
||||
add_subdirectory(sha)
|
||||
add_subdirectory(md4)
|
||||
add_subdirectory(md5)
|
||||
add_subdirectory(modes)
|
||||
add_subdirectory(aes)
|
||||
add_subdirectory(des)
|
||||
add_subdirectory(rc4)
|
||||
add_subdirectory(conf)
|
||||
add_subdirectory(chacha)
|
||||
@@ -80,11 +94,11 @@ add_subdirectory(poly1305)
|
||||
add_subdirectory(curve25519)
|
||||
|
||||
# Level 1, depends only on 0.*
|
||||
add_subdirectory(digest)
|
||||
add_subdirectory(cipher)
|
||||
add_subdirectory(rand)
|
||||
add_subdirectory(digest_extra)
|
||||
add_subdirectory(cipher_extra)
|
||||
add_subdirectory(rand_extra)
|
||||
add_subdirectory(bio)
|
||||
add_subdirectory(bn)
|
||||
add_subdirectory(bn_extra)
|
||||
add_subdirectory(obj)
|
||||
add_subdirectory(asn1)
|
||||
|
||||
@@ -92,11 +106,10 @@ add_subdirectory(asn1)
|
||||
add_subdirectory(engine)
|
||||
add_subdirectory(dh)
|
||||
add_subdirectory(dsa)
|
||||
add_subdirectory(rsa)
|
||||
add_subdirectory(ec)
|
||||
add_subdirectory(rsa_extra)
|
||||
add_subdirectory(ec_extra)
|
||||
add_subdirectory(ecdh)
|
||||
add_subdirectory(ecdsa)
|
||||
add_subdirectory(hmac)
|
||||
add_subdirectory(ecdsa_extra)
|
||||
|
||||
# Level 3
|
||||
add_subdirectory(cmac)
|
||||
@@ -107,13 +120,18 @@ add_subdirectory(x509)
|
||||
add_subdirectory(x509v3)
|
||||
|
||||
# Level 4
|
||||
add_subdirectory(pkcs7)
|
||||
add_subdirectory(pkcs8)
|
||||
|
||||
# Test support code
|
||||
add_subdirectory(test)
|
||||
|
||||
add_subdirectory(fipsmodule)
|
||||
|
||||
add_library(
|
||||
crypto
|
||||
crypto_base
|
||||
|
||||
OBJECT
|
||||
|
||||
cpu-aarch64-linux.c
|
||||
cpu-arm.c
|
||||
@@ -129,98 +147,129 @@ add_library(
|
||||
thread_none.c
|
||||
thread_pthread.c
|
||||
thread_win.c
|
||||
)
|
||||
|
||||
if(FIPS_DELOCATE)
|
||||
SET_SOURCE_FILES_PROPERTIES(fipsmodule/bcm.o PROPERTIES EXTERNAL_OBJECT true)
|
||||
SET_SOURCE_FILES_PROPERTIES(fipsmodule/bcm.o PROPERTIES GENERATED true)
|
||||
|
||||
set(
|
||||
CRYPTO_FIPS_OBJECTS
|
||||
|
||||
fipsmodule/bcm.o
|
||||
)
|
||||
endif()
|
||||
|
||||
add_library(
|
||||
crypto
|
||||
|
||||
$<TARGET_OBJECTS:crypto_base>
|
||||
$<TARGET_OBJECTS:stack>
|
||||
$<TARGET_OBJECTS:lhash>
|
||||
$<TARGET_OBJECTS:err>
|
||||
$<TARGET_OBJECTS:base64>
|
||||
$<TARGET_OBJECTS:bytestring>
|
||||
$<TARGET_OBJECTS:pool>
|
||||
$<TARGET_OBJECTS:sha>
|
||||
$<TARGET_OBJECTS:md4>
|
||||
$<TARGET_OBJECTS:md5>
|
||||
$<TARGET_OBJECTS:digest>
|
||||
$<TARGET_OBJECTS:cipher>
|
||||
$<TARGET_OBJECTS:modes>
|
||||
$<TARGET_OBJECTS:aes>
|
||||
$<TARGET_OBJECTS:des>
|
||||
$<TARGET_OBJECTS:fipsmodule>
|
||||
$<TARGET_OBJECTS:digest_extra>
|
||||
$<TARGET_OBJECTS:cipher_extra>
|
||||
$<TARGET_OBJECTS:rc4>
|
||||
$<TARGET_OBJECTS:conf>
|
||||
$<TARGET_OBJECTS:chacha>
|
||||
$<TARGET_OBJECTS:poly1305>
|
||||
$<TARGET_OBJECTS:curve25519>
|
||||
$<TARGET_OBJECTS:buf>
|
||||
$<TARGET_OBJECTS:bn>
|
||||
$<TARGET_OBJECTS:bn_extra>
|
||||
$<TARGET_OBJECTS:bio>
|
||||
$<TARGET_OBJECTS:rand>
|
||||
$<TARGET_OBJECTS:rand_extra>
|
||||
$<TARGET_OBJECTS:obj>
|
||||
$<TARGET_OBJECTS:asn1>
|
||||
$<TARGET_OBJECTS:engine>
|
||||
$<TARGET_OBJECTS:dh>
|
||||
$<TARGET_OBJECTS:dsa>
|
||||
$<TARGET_OBJECTS:rsa>
|
||||
$<TARGET_OBJECTS:ec>
|
||||
$<TARGET_OBJECTS:rsa_extra>
|
||||
$<TARGET_OBJECTS:ec_extra>
|
||||
$<TARGET_OBJECTS:ecdh>
|
||||
$<TARGET_OBJECTS:ecdsa>
|
||||
$<TARGET_OBJECTS:hmac>
|
||||
$<TARGET_OBJECTS:ecdsa_extra>
|
||||
$<TARGET_OBJECTS:cmac>
|
||||
$<TARGET_OBJECTS:evp>
|
||||
$<TARGET_OBJECTS:hkdf>
|
||||
$<TARGET_OBJECTS:pem>
|
||||
$<TARGET_OBJECTS:x509>
|
||||
$<TARGET_OBJECTS:x509v3>
|
||||
$<TARGET_OBJECTS:pkcs7>
|
||||
$<TARGET_OBJECTS:pkcs8_lib>
|
||||
|
||||
${CRYPTO_FIPS_OBJECTS}
|
||||
)
|
||||
|
||||
if(FIPS_DELOCATE)
|
||||
add_dependencies(crypto bcm_o_target)
|
||||
endif()
|
||||
|
||||
SET_TARGET_PROPERTIES(crypto PROPERTIES LINKER_LANGUAGE C)
|
||||
|
||||
if(NOT MSVC AND NOT ANDROID)
|
||||
target_link_libraries(crypto pthread)
|
||||
endif()
|
||||
|
||||
add_executable(
|
||||
constant_time_test
|
||||
|
||||
constant_time_test.cc
|
||||
|
||||
$<TARGET_OBJECTS:test_support>
|
||||
)
|
||||
|
||||
target_link_libraries(constant_time_test crypto)
|
||||
add_dependencies(all_tests constant_time_test)
|
||||
|
||||
add_executable(
|
||||
thread_test
|
||||
|
||||
thread_test.c
|
||||
|
||||
$<TARGET_OBJECTS:test_support>
|
||||
)
|
||||
|
||||
target_link_libraries(thread_test crypto)
|
||||
add_dependencies(all_tests thread_test)
|
||||
|
||||
add_executable(
|
||||
refcount_test
|
||||
|
||||
refcount_test.cc
|
||||
)
|
||||
|
||||
target_link_libraries(refcount_test crypto)
|
||||
add_dependencies(all_tests refcount_test)
|
||||
|
||||
# TODO(davidben): Convert the remaining tests to GTest.
|
||||
add_executable(
|
||||
crypto_test
|
||||
|
||||
asn1/asn1_test.cc
|
||||
base64/base64_test.cc
|
||||
bio/bio_test.cc
|
||||
bytestring/bytestring_test.cc
|
||||
chacha/chacha_test.cc
|
||||
cipher_extra/aead_test.cc
|
||||
cipher_extra/cipher_test.cc
|
||||
cmac/cmac_test.cc
|
||||
compiler_test.cc
|
||||
constant_time_test.cc
|
||||
curve25519/ed25519_test.cc
|
||||
curve25519/spake25519_test.cc
|
||||
curve25519/x25519_test.cc
|
||||
ecdh/ecdh_test.cc
|
||||
dh/dh_test.cc
|
||||
digest_extra/digest_test.cc
|
||||
dsa/dsa_test.cc
|
||||
ec/ec_test.cc
|
||||
err/err_test.cc
|
||||
rsa/rsa_test.cc
|
||||
evp/evp_extra_test.cc
|
||||
evp/evp_test.cc
|
||||
evp/pbkdf_test.cc
|
||||
evp/scrypt_test.cc
|
||||
fipsmodule/aes/aes_test.cc
|
||||
fipsmodule/bn/bn_test.cc
|
||||
fipsmodule/ec/ec_test.cc
|
||||
fipsmodule/ec/p256-x86_64_test.cc
|
||||
fipsmodule/ecdsa/ecdsa_test.cc
|
||||
fipsmodule/modes/gcm_test.cc
|
||||
fipsmodule/rand/ctrdrbg_test.cc
|
||||
hkdf/hkdf_test.cc
|
||||
hmac_extra/hmac_test.cc
|
||||
lhash/lhash_test.cc
|
||||
obj/obj_test.cc
|
||||
pkcs7/pkcs7_test.cc
|
||||
pkcs8/pkcs8_test.cc
|
||||
pkcs8/pkcs12_test.cc
|
||||
poly1305/poly1305_test.cc
|
||||
pool/pool_test.cc
|
||||
refcount_test.cc
|
||||
rsa_extra/rsa_test.cc
|
||||
test/file_test_gtest.cc
|
||||
thread_test.cc
|
||||
x509/x509_test.cc
|
||||
x509v3/tab_test.cc
|
||||
x509v3/v3name_test.cc
|
||||
|
||||
$<TARGET_OBJECTS:crypto_test_data>
|
||||
$<TARGET_OBJECTS:gtest_main>
|
||||
$<TARGET_OBJECTS:test_support>
|
||||
)
|
||||
|
||||
target_link_libraries(crypto_test crypto gtest)
|
||||
if (WIN32)
|
||||
target_link_libraries(crypto_test ws2_32)
|
||||
endif()
|
||||
add_dependencies(all_tests crypto_test)
|
||||
|
||||
@@ -1,82 +0,0 @@
|
||||
include_directories(../../include)
|
||||
|
||||
if (${ARCH} STREQUAL "x86_64")
|
||||
set(
|
||||
AES_ARCH_SOURCES
|
||||
|
||||
aes-x86_64.${ASM_EXT}
|
||||
aesni-x86_64.${ASM_EXT}
|
||||
bsaes-x86_64.${ASM_EXT}
|
||||
vpaes-x86_64.${ASM_EXT}
|
||||
)
|
||||
endif()
|
||||
|
||||
if (${ARCH} STREQUAL "x86")
|
||||
set(
|
||||
AES_ARCH_SOURCES
|
||||
|
||||
aes-586.${ASM_EXT}
|
||||
vpaes-x86.${ASM_EXT}
|
||||
aesni-x86.${ASM_EXT}
|
||||
)
|
||||
endif()
|
||||
|
||||
if (${ARCH} STREQUAL "arm")
|
||||
set(
|
||||
AES_ARCH_SOURCES
|
||||
|
||||
aes-armv4.${ASM_EXT}
|
||||
bsaes-armv7.${ASM_EXT}
|
||||
aesv8-armx.${ASM_EXT}
|
||||
)
|
||||
endif()
|
||||
|
||||
if (${ARCH} STREQUAL "aarch64")
|
||||
set(
|
||||
AES_ARCH_SOURCES
|
||||
|
||||
aesv8-armx.${ASM_EXT}
|
||||
)
|
||||
endif()
|
||||
|
||||
if (${ARCH} STREQUAL "ppc64le")
|
||||
set(
|
||||
AES_ARCH_SOURCES
|
||||
|
||||
aesp8-ppc.${ASM_EXT}
|
||||
)
|
||||
endif()
|
||||
|
||||
add_library(
|
||||
aes
|
||||
|
||||
OBJECT
|
||||
|
||||
aes.c
|
||||
key_wrap.c
|
||||
mode_wrappers.c
|
||||
|
||||
${AES_ARCH_SOURCES}
|
||||
)
|
||||
|
||||
perlasm(aes-x86_64.${ASM_EXT} asm/aes-x86_64.pl)
|
||||
perlasm(aesni-x86_64.${ASM_EXT} asm/aesni-x86_64.pl)
|
||||
perlasm(bsaes-x86_64.${ASM_EXT} asm/bsaes-x86_64.pl)
|
||||
perlasm(vpaes-x86_64.${ASM_EXT} asm/vpaes-x86_64.pl)
|
||||
perlasm(aes-586.${ASM_EXT} asm/aes-586.pl)
|
||||
perlasm(vpaes-x86.${ASM_EXT} asm/vpaes-x86.pl)
|
||||
perlasm(aesni-x86.${ASM_EXT} asm/aesni-x86.pl)
|
||||
perlasm(aes-armv4.${ASM_EXT} asm/aes-armv4.pl)
|
||||
perlasm(bsaes-armv7.${ASM_EXT} asm/bsaes-armv7.pl)
|
||||
perlasm(aesv8-armx.${ASM_EXT} asm/aesv8-armx.pl)
|
||||
perlasm(aesp8-ppc.${ASM_EXT} asm/aesp8-ppc.pl)
|
||||
|
||||
add_executable(
|
||||
aes_test
|
||||
|
||||
aes_test.cc
|
||||
$<TARGET_OBJECTS:test_support>
|
||||
)
|
||||
|
||||
target_link_libraries(aes_test crypto)
|
||||
add_dependencies(all_tests aes_test)
|
||||
@@ -1,190 +0,0 @@
|
||||
/* Copyright (c) 2015, Google Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include <openssl/aes.h>
|
||||
#include <openssl/crypto.h>
|
||||
|
||||
#include "../internal.h"
|
||||
#include "../test/file_test.h"
|
||||
|
||||
|
||||
static bool TestRaw(FileTest *t) {
|
||||
std::vector<uint8_t> key, plaintext, ciphertext;
|
||||
if (!t->GetBytes(&key, "Key") ||
|
||||
!t->GetBytes(&plaintext, "Plaintext") ||
|
||||
!t->GetBytes(&ciphertext, "Ciphertext")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (plaintext.size() != AES_BLOCK_SIZE ||
|
||||
ciphertext.size() != AES_BLOCK_SIZE) {
|
||||
t->PrintLine("Plaintext or Ciphertext not a block size.");
|
||||
return false;
|
||||
}
|
||||
|
||||
AES_KEY aes_key;
|
||||
if (AES_set_encrypt_key(key.data(), 8 * key.size(), &aes_key) != 0) {
|
||||
t->PrintLine("AES_set_encrypt_key failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Test encryption.
|
||||
uint8_t block[AES_BLOCK_SIZE];
|
||||
AES_encrypt(plaintext.data(), block, &aes_key);
|
||||
if (!t->ExpectBytesEqual(block, AES_BLOCK_SIZE, ciphertext.data(),
|
||||
ciphertext.size())) {
|
||||
t->PrintLine("AES_encrypt gave the wrong output.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Test in-place encryption.
|
||||
OPENSSL_memcpy(block, plaintext.data(), AES_BLOCK_SIZE);
|
||||
AES_encrypt(block, block, &aes_key);
|
||||
if (!t->ExpectBytesEqual(block, AES_BLOCK_SIZE, ciphertext.data(),
|
||||
ciphertext.size())) {
|
||||
t->PrintLine("In-place AES_encrypt gave the wrong output.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (AES_set_decrypt_key(key.data(), 8 * key.size(), &aes_key) != 0) {
|
||||
t->PrintLine("AES_set_decrypt_key failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Test decryption.
|
||||
AES_decrypt(ciphertext.data(), block, &aes_key);
|
||||
if (!t->ExpectBytesEqual(block, AES_BLOCK_SIZE, plaintext.data(),
|
||||
plaintext.size())) {
|
||||
t->PrintLine("AES_decrypt gave the wrong output.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Test in-place decryption.
|
||||
OPENSSL_memcpy(block, ciphertext.data(), AES_BLOCK_SIZE);
|
||||
AES_decrypt(block, block, &aes_key);
|
||||
if (!t->ExpectBytesEqual(block, AES_BLOCK_SIZE, plaintext.data(),
|
||||
plaintext.size())) {
|
||||
t->PrintLine("In-place AES_decrypt gave the wrong output.");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool TestKeyWrap(FileTest *t) {
|
||||
// All test vectors use the default IV, so test both with implicit and
|
||||
// explicit IV.
|
||||
//
|
||||
// TODO(davidben): Find test vectors that use a different IV.
|
||||
static const uint8_t kDefaultIV[] = {
|
||||
0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6,
|
||||
};
|
||||
|
||||
std::vector<uint8_t> key, plaintext, ciphertext;
|
||||
if (!t->GetBytes(&key, "Key") ||
|
||||
!t->GetBytes(&plaintext, "Plaintext") ||
|
||||
!t->GetBytes(&ciphertext, "Ciphertext")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (plaintext.size() + 8 != ciphertext.size()) {
|
||||
t->PrintLine("Invalid Plaintext and Ciphertext lengths.");
|
||||
return false;
|
||||
}
|
||||
|
||||
AES_KEY aes_key;
|
||||
if (AES_set_encrypt_key(key.data(), 8 * key.size(), &aes_key) != 0) {
|
||||
t->PrintLine("AES_set_encrypt_key failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
std::unique_ptr<uint8_t[]> buf(new uint8_t[ciphertext.size()]);
|
||||
if (AES_wrap_key(&aes_key, nullptr /* iv */, buf.get(), plaintext.data(),
|
||||
plaintext.size()) != static_cast<int>(ciphertext.size()) ||
|
||||
!t->ExpectBytesEqual(buf.get(), ciphertext.size(), ciphertext.data(),
|
||||
ciphertext.size())) {
|
||||
t->PrintLine("AES_wrap_key with implicit IV failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
OPENSSL_memset(buf.get(), 0, ciphertext.size());
|
||||
if (AES_wrap_key(&aes_key, kDefaultIV, buf.get(), plaintext.data(),
|
||||
plaintext.size()) != static_cast<int>(ciphertext.size()) ||
|
||||
!t->ExpectBytesEqual(buf.get(), ciphertext.size(), ciphertext.data(),
|
||||
ciphertext.size())) {
|
||||
t->PrintLine("AES_wrap_key with explicit IV failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (AES_set_decrypt_key(key.data(), 8 * key.size(), &aes_key) != 0) {
|
||||
t->PrintLine("AES_set_decrypt_key failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
buf.reset(new uint8_t[plaintext.size()]);
|
||||
if (AES_unwrap_key(&aes_key, nullptr /* iv */, buf.get(), ciphertext.data(),
|
||||
ciphertext.size()) != static_cast<int>(plaintext.size()) ||
|
||||
!t->ExpectBytesEqual(buf.get(), plaintext.size(), plaintext.data(),
|
||||
plaintext.size())) {
|
||||
t->PrintLine("AES_unwrap_key with implicit IV failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
OPENSSL_memset(buf.get(), 0, plaintext.size());
|
||||
if (AES_unwrap_key(&aes_key, kDefaultIV, buf.get(), ciphertext.data(),
|
||||
ciphertext.size()) != static_cast<int>(plaintext.size()) ||
|
||||
!t->ExpectBytesEqual(buf.get(), plaintext.size(), plaintext.data(),
|
||||
plaintext.size())) {
|
||||
t->PrintLine("AES_unwrap_key with explicit IV failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
ciphertext[0] ^= 1;
|
||||
if (AES_unwrap_key(&aes_key, nullptr /* iv */, buf.get(), ciphertext.data(),
|
||||
ciphertext.size()) != -1) {
|
||||
t->PrintLine("AES_unwrap_key with bad input unexpectedly succeeded.");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool TestAES(FileTest *t, void *arg) {
|
||||
if (t->GetParameter() == "Raw") {
|
||||
return TestRaw(t);
|
||||
}
|
||||
if (t->GetParameter() == "KeyWrap") {
|
||||
return TestKeyWrap(t);
|
||||
}
|
||||
|
||||
t->PrintLine("Unknown mode '%s'.", t->GetParameter().c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
CRYPTO_library_init();
|
||||
|
||||
if (argc != 2) {
|
||||
fprintf(stderr, "%s <test file.txt>\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return FileTestMain(TestAES, nullptr, argv[1]);
|
||||
}
|
||||
@@ -1,87 +0,0 @@
|
||||
/* ====================================================================
|
||||
* Copyright (c) 2002-2006 The OpenSSL Project. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. All advertising materials mentioning features or use of this
|
||||
* software must display the following acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
|
||||
*
|
||||
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
|
||||
* endorse or promote products derived from this software without
|
||||
* prior written permission. For written permission, please contact
|
||||
* openssl-core@openssl.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "OpenSSL"
|
||||
* nor may "OpenSSL" appear in their names without prior written
|
||||
* permission of the OpenSSL Project.
|
||||
*
|
||||
* 6. Redistributions of any form whatsoever must retain the following
|
||||
* acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit (http://www.openssl.org/)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
|
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ==================================================================== */
|
||||
|
||||
#ifndef OPENSSL_HEADER_AES_INTERNAL_H
|
||||
#define OPENSSL_HEADER_AES_INTERNAL_H
|
||||
|
||||
#include <openssl/base.h>
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(_MSC_VER) && \
|
||||
(defined(_M_IX86) || defined(_M_AMD64) || defined(_M_X64))
|
||||
#define SWAP(x) (_lrotl(x, 8) & 0x00ff00ff | _lrotr(x, 8) & 0xff00ff00)
|
||||
#define GETU32(p) SWAP(*((uint32_t *)(p)))
|
||||
#define PUTU32(ct, st) \
|
||||
{ *((uint32_t *)(ct)) = SWAP((st)); }
|
||||
#else
|
||||
#define GETU32(pt) \
|
||||
(((uint32_t)(pt)[0] << 24) ^ ((uint32_t)(pt)[1] << 16) ^ \
|
||||
((uint32_t)(pt)[2] << 8) ^ ((uint32_t)(pt)[3]))
|
||||
#define PUTU32(ct, st) \
|
||||
{ \
|
||||
(ct)[0] = (uint8_t)((st) >> 24); \
|
||||
(ct)[1] = (uint8_t)((st) >> 16); \
|
||||
(ct)[2] = (uint8_t)((st) >> 8); \
|
||||
(ct)[3] = (uint8_t)(st); \
|
||||
}
|
||||
#endif
|
||||
|
||||
#define MAXKC (256 / 32)
|
||||
#define MAXKB (256 / 8)
|
||||
#define MAXNR 14
|
||||
|
||||
|
||||
#if defined(__cplusplus)
|
||||
} /* extern C */
|
||||
#endif
|
||||
|
||||
#endif /* OPENSSL_HEADER_AES_INTERNAL_H */
|
||||
@@ -28,7 +28,6 @@ add_library(
|
||||
f_enum.c
|
||||
f_int.c
|
||||
f_string.c
|
||||
t_bitst.c
|
||||
tasn_dec.c
|
||||
tasn_enc.c
|
||||
tasn_fre.c
|
||||
@@ -36,17 +35,4 @@ add_library(
|
||||
tasn_typ.c
|
||||
tasn_utl.c
|
||||
time_support.c
|
||||
x_bignum.c
|
||||
x_long.c
|
||||
)
|
||||
|
||||
add_executable(
|
||||
asn1_test
|
||||
|
||||
asn1_test.cc
|
||||
|
||||
$<TARGET_OBJECTS:test_support>
|
||||
)
|
||||
|
||||
target_link_libraries(asn1_test crypto)
|
||||
add_dependencies(all_tests asn1_test)
|
||||
|
||||
@@ -140,6 +140,21 @@ void *ASN1_item_d2i_fp(const ASN1_ITEM *it, FILE *in, void *x)
|
||||
}
|
||||
#endif
|
||||
|
||||
typedef struct asn1_const_ctx_st
|
||||
{
|
||||
const unsigned char *p;/* work char pointer */
|
||||
int eos; /* end of sequence read for indefinite encoding */
|
||||
int error; /* error code to use when returning an error */
|
||||
int inf; /* constructed if 0x20, indefinite is 0x21 */
|
||||
int tag; /* tag from last 'get object' */
|
||||
int xclass; /* class from last 'get object' */
|
||||
long slen; /* length of last 'get object' */
|
||||
const unsigned char *max; /* largest value of p allowed */
|
||||
const unsigned char *q;/* temporary variable */
|
||||
const unsigned char **pp;/* variable */
|
||||
int line; /* used in error processing */
|
||||
} ASN1_const_CTX;
|
||||
|
||||
#define HEADER_SIZE 8
|
||||
#define ASN1_CHUNK_INITIAL_SIZE (16 * 1024)
|
||||
static int asn1_d2i_read_bio(BIO *in, BUF_MEM **pb)
|
||||
|
||||
@@ -148,7 +148,7 @@ int asn1_generalizedtime_to_tm(struct tm *tm, const ASN1_GENERALIZEDTIME *d)
|
||||
if (a[o] == 'Z')
|
||||
o++;
|
||||
else if ((a[o] == '+') || (a[o] == '-')) {
|
||||
int offsign = a[o] == '-' ? -1 : 1, offset = 0;
|
||||
int offsign = a[o] == '-' ? 1 : -1, offset = 0;
|
||||
o++;
|
||||
if (o + 4 > l)
|
||||
goto err;
|
||||
|
||||
@@ -91,31 +91,3 @@ int ASN1_PRINTABLE_type(const unsigned char *s, int len)
|
||||
return (V_ASN1_IA5STRING);
|
||||
return (V_ASN1_PRINTABLESTRING);
|
||||
}
|
||||
|
||||
int ASN1_UNIVERSALSTRING_to_string(ASN1_UNIVERSALSTRING *s)
|
||||
{
|
||||
int i;
|
||||
unsigned char *p;
|
||||
|
||||
if (s->type != V_ASN1_UNIVERSALSTRING)
|
||||
return (0);
|
||||
if ((s->length % 4) != 0)
|
||||
return (0);
|
||||
p = s->data;
|
||||
for (i = 0; i < s->length; i += 4) {
|
||||
if ((p[0] != '\0') || (p[1] != '\0') || (p[2] != '\0'))
|
||||
break;
|
||||
else
|
||||
p += 4;
|
||||
}
|
||||
if (i < s->length)
|
||||
return (0);
|
||||
p = s->data;
|
||||
for (i = 3; i < s->length; i += 4) {
|
||||
*(p++) = s->data[i];
|
||||
}
|
||||
*(p) = '\0';
|
||||
s->length /= 4;
|
||||
s->type = ASN1_PRINTABLE_type(s->data, s->length);
|
||||
return (1);
|
||||
}
|
||||
|
||||
@@ -62,6 +62,9 @@
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.h>
|
||||
#include <openssl/obj.h>
|
||||
#include <openssl/stack.h>
|
||||
|
||||
DEFINE_STACK_OF(ASN1_STRING_TABLE)
|
||||
|
||||
static STACK_OF(ASN1_STRING_TABLE) *stable = NULL;
|
||||
static void st_free(ASN1_STRING_TABLE *tbl);
|
||||
|
||||
+17
-9
@@ -114,7 +114,7 @@ int ASN1_TIME_check(ASN1_TIME *t)
|
||||
ASN1_GENERALIZEDTIME *ASN1_TIME_to_generalizedtime(ASN1_TIME *t,
|
||||
ASN1_GENERALIZEDTIME **out)
|
||||
{
|
||||
ASN1_GENERALIZEDTIME *ret;
|
||||
ASN1_GENERALIZEDTIME *ret = NULL;
|
||||
char *str;
|
||||
int newlen;
|
||||
|
||||
@@ -123,22 +123,21 @@ ASN1_GENERALIZEDTIME *ASN1_TIME_to_generalizedtime(ASN1_TIME *t,
|
||||
|
||||
if (!out || !*out) {
|
||||
if (!(ret = ASN1_GENERALIZEDTIME_new()))
|
||||
return NULL;
|
||||
if (out)
|
||||
*out = ret;
|
||||
} else
|
||||
goto err;
|
||||
} else {
|
||||
ret = *out;
|
||||
}
|
||||
|
||||
/* If already GeneralizedTime just copy across */
|
||||
if (t->type == V_ASN1_GENERALIZEDTIME) {
|
||||
if (!ASN1_STRING_set(ret, t->data, t->length))
|
||||
return NULL;
|
||||
return ret;
|
||||
goto err;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* grow the string */
|
||||
if (!ASN1_STRING_set(ret, NULL, t->length + 2))
|
||||
return NULL;
|
||||
goto err;
|
||||
/* ASN1_STRING_set() allocated 'len + 1' bytes. */
|
||||
newlen = t->length + 2 + 1;
|
||||
str = (char *)ret->data;
|
||||
@@ -150,9 +149,18 @@ ASN1_GENERALIZEDTIME *ASN1_TIME_to_generalizedtime(ASN1_TIME *t,
|
||||
|
||||
BUF_strlcat(str, (char *)t->data, newlen);
|
||||
|
||||
return ret;
|
||||
done:
|
||||
if (out != NULL && *out == NULL)
|
||||
*out = ret;
|
||||
return ret;
|
||||
|
||||
err:
|
||||
if (out == NULL || *out != ret)
|
||||
ASN1_GENERALIZEDTIME_free(ret);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
int ASN1_TIME_set_string(ASN1_TIME *s, const char *str)
|
||||
{
|
||||
ASN1_TIME t;
|
||||
|
||||
@@ -127,7 +127,7 @@ int asn1_utctime_to_tm(struct tm *tm, const ASN1_UTCTIME *d)
|
||||
if (a[o] == 'Z')
|
||||
o++;
|
||||
else if ((a[o] == '+') || (a[o] == '-')) {
|
||||
int offsign = a[o] == '-' ? -1 : 1, offset = 0;
|
||||
int offsign = a[o] == '-' ? 1 : -1, offset = 0;
|
||||
o++;
|
||||
if (o + 4 > l)
|
||||
goto err;
|
||||
|
||||
@@ -107,30 +107,6 @@ static int asn1_get_length(const unsigned char **pp, int *inf, long *rl,
|
||||
long max);
|
||||
static void asn1_put_length(unsigned char **pp, int length);
|
||||
|
||||
static int _asn1_check_infinite_end(const unsigned char **p, long len)
|
||||
{
|
||||
/*
|
||||
* If there is 0 or 1 byte left, the length check should pick things up
|
||||
*/
|
||||
if (len <= 0)
|
||||
return (1);
|
||||
else if ((len >= 2) && ((*p)[0] == 0) && ((*p)[1] == 0)) {
|
||||
(*p) += 2;
|
||||
return (1);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
int ASN1_check_infinite_end(unsigned char **p, long len)
|
||||
{
|
||||
return _asn1_check_infinite_end((const unsigned char **)p, len);
|
||||
}
|
||||
|
||||
int ASN1_const_check_infinite_end(const unsigned char **p, long len)
|
||||
{
|
||||
return _asn1_check_infinite_end(p, len);
|
||||
}
|
||||
|
||||
int ASN1_get_object(const unsigned char **pp, long *plength, int *ptag,
|
||||
int *pclass, long omax)
|
||||
{
|
||||
@@ -327,31 +303,6 @@ int ASN1_object_size(int constructed, int length, int tag)
|
||||
return ret + length;
|
||||
}
|
||||
|
||||
static int _asn1_Finish(ASN1_const_CTX *c)
|
||||
{
|
||||
if ((c->inf == (1 | V_ASN1_CONSTRUCTED)) && (!c->eos)) {
|
||||
if (!ASN1_const_check_infinite_end(&c->p, c->slen)) {
|
||||
c->error = ASN1_R_MISSING_ASN1_EOS;
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
if (((c->slen != 0) && !(c->inf & 1)) || ((c->slen < 0) && (c->inf & 1))) {
|
||||
c->error = ASN1_R_ASN1_LENGTH_MISMATCH;
|
||||
return (0);
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
|
||||
int asn1_Finish(ASN1_CTX *c)
|
||||
{
|
||||
return _asn1_Finish((ASN1_const_CTX *)c);
|
||||
}
|
||||
|
||||
int asn1_const_Finish(ASN1_const_CTX *c)
|
||||
{
|
||||
return _asn1_Finish(c);
|
||||
}
|
||||
|
||||
int ASN1_STRING_copy(ASN1_STRING *dst, const ASN1_STRING *str)
|
||||
{
|
||||
if (str == NULL)
|
||||
|
||||
@@ -72,7 +72,7 @@ extern "C" {
|
||||
/* Wrapper functions for time functions. */
|
||||
|
||||
/* OPENSSL_gmtime wraps |gmtime_r|. See the manual page for that function. */
|
||||
struct tm *OPENSSL_gmtime(const time_t *timer, struct tm *result);
|
||||
struct tm *OPENSSL_gmtime(const time_t *time, struct tm *result);
|
||||
|
||||
/* OPENSSL_gmtime_adj updates |tm| by adding |offset_day| days and |offset_sec|
|
||||
* seconds. */
|
||||
|
||||
+12
-29
@@ -14,10 +14,13 @@
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <openssl/asn1.h>
|
||||
#include <openssl/crypto.h>
|
||||
#include <openssl/err.h>
|
||||
|
||||
#include "../test/test_util.h"
|
||||
|
||||
|
||||
// kTag128 is an ASN.1 structure with a universal tag with number 128.
|
||||
static const uint8_t kTag128[] = {
|
||||
@@ -38,42 +41,22 @@ static const uint8_t kTagOverflow[] = {
|
||||
0x1f, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x01, 0x00,
|
||||
};
|
||||
|
||||
static bool TestLargeTags() {
|
||||
TEST(ASN1Test, LargeTags) {
|
||||
const uint8_t *p = kTag258;
|
||||
bssl::UniquePtr<ASN1_TYPE> obj(d2i_ASN1_TYPE(NULL, &p, sizeof(kTag258)));
|
||||
if (obj) {
|
||||
fprintf(stderr, "Parsed value with illegal tag (type = %d).\n", obj->type);
|
||||
return false;
|
||||
}
|
||||
EXPECT_FALSE(obj) << "Parsed value with illegal tag" << obj->type;
|
||||
ERR_clear_error();
|
||||
|
||||
p = kTagOverflow;
|
||||
obj.reset(d2i_ASN1_TYPE(NULL, &p, sizeof(kTagOverflow)));
|
||||
if (obj) {
|
||||
fprintf(stderr, "Parsed value with tag overflow (type = %d).\n", obj->type);
|
||||
return false;
|
||||
}
|
||||
EXPECT_FALSE(obj) << "Parsed value with tag overflow" << obj->type;
|
||||
ERR_clear_error();
|
||||
|
||||
p = kTag128;
|
||||
obj.reset(d2i_ASN1_TYPE(NULL, &p, sizeof(kTag128)));
|
||||
if (!obj || obj->type != 128 || obj->value.asn1_string->length != 1 ||
|
||||
obj->value.asn1_string->data[0] != 0) {
|
||||
fprintf(stderr, "Failed to parse value with tag 128.\n");
|
||||
ERR_print_errors_fp(stderr);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main() {
|
||||
CRYPTO_library_init();
|
||||
|
||||
if (!TestLargeTags()) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("PASS\n");
|
||||
return 0;
|
||||
ASSERT_TRUE(obj);
|
||||
EXPECT_EQ(128, obj->type);
|
||||
const uint8_t kZero = 0;
|
||||
EXPECT_EQ(Bytes(&kZero, 1), Bytes(obj->value.asn1_string->data,
|
||||
obj->value.asn1_string->length));
|
||||
}
|
||||
|
||||
@@ -1,103 +0,0 @@
|
||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young (eay@cryptsoft.com).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young (eay@cryptsoft.com)"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.] */
|
||||
|
||||
#include <openssl/asn1.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl/mem.h>
|
||||
|
||||
int ASN1_BIT_STRING_name_print(BIO *out, ASN1_BIT_STRING *bs,
|
||||
BIT_STRING_BITNAME *tbl, int indent)
|
||||
{
|
||||
BIT_STRING_BITNAME *bnam;
|
||||
char first = 1;
|
||||
BIO_printf(out, "%*s", indent, "");
|
||||
for (bnam = tbl; bnam->lname; bnam++) {
|
||||
if (ASN1_BIT_STRING_get_bit(bs, bnam->bitnum)) {
|
||||
if (!first)
|
||||
BIO_puts(out, ", ");
|
||||
BIO_puts(out, bnam->lname);
|
||||
first = 0;
|
||||
}
|
||||
}
|
||||
BIO_puts(out, "\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ASN1_BIT_STRING_set_asc(ASN1_BIT_STRING *bs, char *name, int value,
|
||||
BIT_STRING_BITNAME *tbl)
|
||||
{
|
||||
int bitnum;
|
||||
bitnum = ASN1_BIT_STRING_num_asc(name, tbl);
|
||||
if (bitnum < 0)
|
||||
return 0;
|
||||
if (bs) {
|
||||
if (!ASN1_BIT_STRING_set_bit(bs, bitnum, value))
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int ASN1_BIT_STRING_num_asc(char *name, BIT_STRING_BITNAME *tbl)
|
||||
{
|
||||
BIT_STRING_BITNAME *bnam;
|
||||
for (bnam = tbl; bnam->lname; bnam++) {
|
||||
if (!strcmp(bnam->sname, name) || !strcmp(bnam->lname, name))
|
||||
return bnam->bitnum;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
@@ -171,7 +171,7 @@ int OPENSSL_gmtime_adj(struct tm *tm, int off_day, long offset_sec) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
int OPENSSL_gmtime_diff(int *pday, int *psec, const struct tm *from,
|
||||
int OPENSSL_gmtime_diff(int *out_days, int *out_secs, const struct tm *from,
|
||||
const struct tm *to) {
|
||||
int from_sec, to_sec, diff_sec;
|
||||
long from_jd, to_jd, diff_day;
|
||||
@@ -195,11 +195,11 @@ int OPENSSL_gmtime_diff(int *pday, int *psec, const struct tm *from,
|
||||
diff_sec -= SECS_PER_DAY;
|
||||
}
|
||||
|
||||
if (pday) {
|
||||
*pday = (int)diff_day;
|
||||
if (out_days) {
|
||||
*out_days = (int)diff_day;
|
||||
}
|
||||
if (psec) {
|
||||
*psec = diff_sec;
|
||||
if (out_secs) {
|
||||
*out_secs = diff_sec;
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
@@ -1,153 +0,0 @@
|
||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young (eay@cryptsoft.com).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young (eay@cryptsoft.com)"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.] */
|
||||
|
||||
#include <openssl/asn1.h>
|
||||
|
||||
#include <openssl/asn1t.h>
|
||||
#include <openssl/bn.h>
|
||||
|
||||
/*
|
||||
* Custom primitive type for BIGNUM handling. This reads in an ASN1_INTEGER
|
||||
* as a BIGNUM directly. Currently it ignores the sign which isn't a problem
|
||||
* since all BIGNUMs used are non negative and anything that looks negative
|
||||
* is normally due to an encoding error.
|
||||
*/
|
||||
|
||||
#define BN_SENSITIVE 1
|
||||
|
||||
static int bn_new(ASN1_VALUE **pval, const ASN1_ITEM *it);
|
||||
static void bn_free(ASN1_VALUE **pval, const ASN1_ITEM *it);
|
||||
|
||||
static int bn_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype,
|
||||
const ASN1_ITEM *it);
|
||||
static int bn_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
|
||||
int utype, char *free_cont, const ASN1_ITEM *it);
|
||||
|
||||
static const ASN1_PRIMITIVE_FUNCS bignum_pf = {
|
||||
NULL, 0,
|
||||
bn_new,
|
||||
bn_free,
|
||||
0,
|
||||
bn_c2i,
|
||||
bn_i2c,
|
||||
NULL /* prim_print */ ,
|
||||
};
|
||||
|
||||
ASN1_ITEM_start(BIGNUM)
|
||||
ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &bignum_pf, 0, "BIGNUM"
|
||||
ASN1_ITEM_end(BIGNUM)
|
||||
|
||||
ASN1_ITEM_start(CBIGNUM)
|
||||
ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &bignum_pf, BN_SENSITIVE, "BIGNUM"
|
||||
ASN1_ITEM_end(CBIGNUM)
|
||||
|
||||
static int bn_new(ASN1_VALUE **pval, const ASN1_ITEM *it)
|
||||
{
|
||||
*pval = (ASN1_VALUE *)BN_new();
|
||||
if (*pval)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void bn_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
|
||||
{
|
||||
if (!*pval)
|
||||
return;
|
||||
if (it->size & BN_SENSITIVE)
|
||||
BN_clear_free((BIGNUM *)*pval);
|
||||
else
|
||||
BN_free((BIGNUM *)*pval);
|
||||
*pval = NULL;
|
||||
}
|
||||
|
||||
static int bn_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype,
|
||||
const ASN1_ITEM *it)
|
||||
{
|
||||
BIGNUM *bn;
|
||||
int pad;
|
||||
if (!*pval)
|
||||
return -1;
|
||||
bn = (BIGNUM *)*pval;
|
||||
/* If MSB set in an octet we need a padding byte */
|
||||
if (BN_num_bits(bn) & 0x7)
|
||||
pad = 0;
|
||||
else
|
||||
pad = 1;
|
||||
if (cont) {
|
||||
if (pad)
|
||||
*cont++ = 0;
|
||||
BN_bn2bin(bn, cont);
|
||||
}
|
||||
return pad + BN_num_bytes(bn);
|
||||
}
|
||||
|
||||
static int bn_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
|
||||
int utype, char *free_cont, const ASN1_ITEM *it)
|
||||
{
|
||||
BIGNUM *bn;
|
||||
if (!*pval) {
|
||||
if (!bn_new(pval, it)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
bn = (BIGNUM *)*pval;
|
||||
if (!BN_bin2bn(cont, len, bn)) {
|
||||
bn_free(pval, it);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
@@ -1,200 +0,0 @@
|
||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young (eay@cryptsoft.com).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young (eay@cryptsoft.com)"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.] */
|
||||
|
||||
#include <openssl/asn1.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl/asn1t.h>
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.h>
|
||||
|
||||
#include "../internal.h"
|
||||
|
||||
|
||||
/*
|
||||
* Custom primitive type for long handling. This converts between an
|
||||
* ASN1_INTEGER and a long directly.
|
||||
*/
|
||||
|
||||
static int long_new(ASN1_VALUE **pval, const ASN1_ITEM *it);
|
||||
static void long_free(ASN1_VALUE **pval, const ASN1_ITEM *it);
|
||||
|
||||
static int long_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype,
|
||||
const ASN1_ITEM *it);
|
||||
static int long_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
|
||||
int utype, char *free_cont, const ASN1_ITEM *it);
|
||||
static int long_print(BIO *out, ASN1_VALUE **pval, const ASN1_ITEM *it,
|
||||
int indent, const ASN1_PCTX *pctx);
|
||||
|
||||
static const ASN1_PRIMITIVE_FUNCS long_pf = {
|
||||
NULL, 0,
|
||||
long_new,
|
||||
long_free,
|
||||
long_free, /* Clear should set to initial value */
|
||||
long_c2i,
|
||||
long_i2c,
|
||||
long_print
|
||||
};
|
||||
|
||||
ASN1_ITEM_start(LONG)
|
||||
ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &long_pf, ASN1_LONG_UNDEF, "LONG"
|
||||
ASN1_ITEM_end(LONG)
|
||||
|
||||
ASN1_ITEM_start(ZLONG)
|
||||
ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &long_pf, 0, "ZLONG"
|
||||
ASN1_ITEM_end(ZLONG)
|
||||
|
||||
static int long_new(ASN1_VALUE **pval, const ASN1_ITEM *it)
|
||||
{
|
||||
*(long *)pval = it->size;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void long_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
|
||||
{
|
||||
*(long *)pval = it->size;
|
||||
}
|
||||
|
||||
static int long_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype,
|
||||
const ASN1_ITEM *it)
|
||||
{
|
||||
long ltmp;
|
||||
unsigned long utmp;
|
||||
int clen, pad, i;
|
||||
/* this exists to bypass broken gcc optimization */
|
||||
char *cp = (char *)pval;
|
||||
|
||||
/* use memcpy, because we may not be long aligned */
|
||||
OPENSSL_memcpy(<mp, cp, sizeof(long));
|
||||
|
||||
if (ltmp == it->size)
|
||||
return -1;
|
||||
/*
|
||||
* Convert the long to positive: we subtract one if negative so we can
|
||||
* cleanly handle the padding if only the MSB of the leading octet is
|
||||
* set.
|
||||
*/
|
||||
if (ltmp < 0)
|
||||
utmp = -ltmp - 1;
|
||||
else
|
||||
utmp = ltmp;
|
||||
clen = BN_num_bits_word(utmp);
|
||||
/* If MSB of leading octet set we need to pad */
|
||||
if (!(clen & 0x7))
|
||||
pad = 1;
|
||||
else
|
||||
pad = 0;
|
||||
|
||||
/* Convert number of bits to number of octets */
|
||||
clen = (clen + 7) >> 3;
|
||||
|
||||
if (cont) {
|
||||
if (pad)
|
||||
*cont++ = (ltmp < 0) ? 0xff : 0;
|
||||
for (i = clen - 1; i >= 0; i--) {
|
||||
cont[i] = (unsigned char)(utmp & 0xff);
|
||||
if (ltmp < 0)
|
||||
cont[i] ^= 0xff;
|
||||
utmp >>= 8;
|
||||
}
|
||||
}
|
||||
return clen + pad;
|
||||
}
|
||||
|
||||
static int long_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
|
||||
int utype, char *free_cont, const ASN1_ITEM *it)
|
||||
{
|
||||
int neg, i;
|
||||
long ltmp;
|
||||
unsigned long utmp = 0;
|
||||
char *cp = (char *)pval;
|
||||
if (len > (int)sizeof(long)) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_INTEGER_TOO_LARGE_FOR_LONG);
|
||||
return 0;
|
||||
}
|
||||
/* Is it negative? */
|
||||
if (len && (cont[0] & 0x80))
|
||||
neg = 1;
|
||||
else
|
||||
neg = 0;
|
||||
utmp = 0;
|
||||
for (i = 0; i < len; i++) {
|
||||
utmp <<= 8;
|
||||
if (neg)
|
||||
utmp |= cont[i] ^ 0xff;
|
||||
else
|
||||
utmp |= cont[i];
|
||||
}
|
||||
ltmp = (long)utmp;
|
||||
if (neg) {
|
||||
ltmp++;
|
||||
ltmp = -ltmp;
|
||||
}
|
||||
if (ltmp == it->size) {
|
||||
OPENSSL_PUT_ERROR(ASN1, ASN1_R_INTEGER_TOO_LARGE_FOR_LONG);
|
||||
return 0;
|
||||
}
|
||||
OPENSSL_memcpy(cp, <mp, sizeof(long));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int long_print(BIO *out, ASN1_VALUE **pval, const ASN1_ITEM *it,
|
||||
int indent, const ASN1_PCTX *pctx)
|
||||
{
|
||||
return BIO_printf(out, "%ld\n", *(long *)pval);
|
||||
}
|
||||
@@ -7,14 +7,3 @@ add_library(
|
||||
|
||||
base64.c
|
||||
)
|
||||
|
||||
add_executable(
|
||||
base64_test
|
||||
|
||||
base64_test.cc
|
||||
|
||||
$<TARGET_OBJECTS:test_support>
|
||||
)
|
||||
|
||||
target_link_libraries(base64_test crypto)
|
||||
add_dependencies(all_tests base64_test)
|
||||
|
||||
+64
-42
@@ -65,12 +65,38 @@
|
||||
#include "../internal.h"
|
||||
|
||||
|
||||
/* Encoding. */
|
||||
// constant_time_lt_args_8 behaves like |constant_time_lt_8| but takes |uint8_t|
|
||||
// arguments for a slightly simpler implementation.
|
||||
static inline uint8_t constant_time_lt_args_8(uint8_t a, uint8_t b) {
|
||||
crypto_word_t aw = a;
|
||||
crypto_word_t bw = b;
|
||||
// |crypto_word_t| is larger than |uint8_t|, so |aw| and |bw| have the same
|
||||
// MSB. |aw| < |bw| iff MSB(|aw| - |bw|) is 1.
|
||||
return constant_time_msb_w(aw - bw);
|
||||
}
|
||||
|
||||
static const unsigned char data_bin2ascii[65] =
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
// constant_time_in_range_8 returns |CONSTTIME_TRUE_8| if |min| <= |a| <= |max|
|
||||
// and |CONSTTIME_FALSE_8| otherwise.
|
||||
static inline uint8_t constant_time_in_range_8(uint8_t a, uint8_t min,
|
||||
uint8_t max) {
|
||||
a -= min;
|
||||
return constant_time_lt_args_8(a, max - min + 1);
|
||||
}
|
||||
|
||||
#define conv_bin2ascii(a) (data_bin2ascii[(a) & 0x3f])
|
||||
// Encoding.
|
||||
|
||||
static uint8_t conv_bin2ascii(uint8_t a) {
|
||||
// Since PEM is sometimes used to carry private keys, we encode base64 data
|
||||
// itself in constant-time.
|
||||
a &= 0x3f;
|
||||
uint8_t ret = constant_time_select_8(constant_time_eq_8(a, 62), '+', '/');
|
||||
ret =
|
||||
constant_time_select_8(constant_time_lt_args_8(a, 62), a - 52 + '0', ret);
|
||||
ret =
|
||||
constant_time_select_8(constant_time_lt_args_8(a, 52), a - 26 + 'a', ret);
|
||||
ret = constant_time_select_8(constant_time_lt_args_8(a, 26), a + 'A', ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
OPENSSL_COMPILE_ASSERT(sizeof(((EVP_ENCODE_CTX *)(NULL))->data) % 3 == 0,
|
||||
data_length_must_be_multiple_of_base64_chunk_size);
|
||||
@@ -157,8 +183,8 @@ void EVP_EncodeUpdate(EVP_ENCODE_CTX *ctx, uint8_t *out, int *out_len,
|
||||
ctx->data_used = (unsigned)in_len;
|
||||
|
||||
if (total > INT_MAX) {
|
||||
/* We cannot signal an error, but we can at least avoid making *out_len
|
||||
* negative. */
|
||||
// We cannot signal an error, but we can at least avoid making *out_len
|
||||
// negative.
|
||||
total = 0;
|
||||
}
|
||||
*out_len = (int)total;
|
||||
@@ -175,8 +201,8 @@ void EVP_EncodeFinal(EVP_ENCODE_CTX *ctx, uint8_t *out, int *out_len) {
|
||||
out[encoded] = '\0';
|
||||
ctx->data_used = 0;
|
||||
|
||||
/* ctx->data_used is bounded by sizeof(ctx->data), so this does not
|
||||
* overflow. */
|
||||
// ctx->data_used is bounded by sizeof(ctx->data), so this does not
|
||||
// overflow.
|
||||
assert(encoded <= INT_MAX);
|
||||
*out_len = (int)encoded;
|
||||
}
|
||||
@@ -214,7 +240,7 @@ size_t EVP_EncodeBlock(uint8_t *dst, const uint8_t *src, size_t src_len) {
|
||||
}
|
||||
|
||||
|
||||
/* Decoding. */
|
||||
// Decoding.
|
||||
|
||||
int EVP_DecodedLength(size_t *out_len, size_t len) {
|
||||
if (len % 4 != 0) {
|
||||
@@ -229,35 +255,31 @@ void EVP_DecodeInit(EVP_ENCODE_CTX *ctx) {
|
||||
OPENSSL_memset(ctx, 0, sizeof(EVP_ENCODE_CTX));
|
||||
}
|
||||
|
||||
/* kBase64ASCIIToBinData maps characters (c < 128) to their base64 value, or
|
||||
* else 0xff if they are invalid. As a special case, the padding character
|
||||
* ('=') is mapped to zero. */
|
||||
static const uint8_t kBase64ASCIIToBinData[128] = {
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3e, 0xff, 0xff, 0xff, 0x3f,
|
||||
0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0xff, 0xff,
|
||||
0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
|
||||
0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12,
|
||||
0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24,
|
||||
0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30,
|
||||
0x31, 0x32, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
};
|
||||
|
||||
static uint8_t base64_ascii_to_bin(uint8_t a) {
|
||||
if (a >= 128) {
|
||||
return 0xFF;
|
||||
}
|
||||
// Since PEM is sometimes used to carry private keys, we decode base64 data
|
||||
// itself in constant-time.
|
||||
const uint8_t is_upper = constant_time_in_range_8(a, 'A', 'Z');
|
||||
const uint8_t is_lower = constant_time_in_range_8(a, 'a', 'z');
|
||||
const uint8_t is_digit = constant_time_in_range_8(a, '0', '9');
|
||||
const uint8_t is_plus = constant_time_eq_8(a, '+');
|
||||
const uint8_t is_slash = constant_time_eq_8(a, '/');
|
||||
const uint8_t is_equals = constant_time_eq_8(a, '=');
|
||||
|
||||
return kBase64ASCIIToBinData[a];
|
||||
uint8_t ret = 0xff; // 0xff signals invalid.
|
||||
ret = constant_time_select_8(is_upper, a - 'A', ret); // [0,26)
|
||||
ret = constant_time_select_8(is_lower, a - 'a' + 26, ret); // [26,52)
|
||||
ret = constant_time_select_8(is_digit, a - '0' + 52, ret); // [52,62)
|
||||
ret = constant_time_select_8(is_plus, 62, ret);
|
||||
ret = constant_time_select_8(is_slash, 63, ret);
|
||||
// Padding maps to zero, to be further handled by the caller.
|
||||
ret = constant_time_select_8(is_equals, 0, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* base64_decode_quad decodes a single “quad” (i.e. four characters) of base64
|
||||
* data and writes up to three bytes to |out|. It sets |*out_num_bytes| to the
|
||||
* number of bytes written, which will be less than three if the quad ended
|
||||
* with padding. It returns one on success or zero on error. */
|
||||
// base64_decode_quad decodes a single “quad” (i.e. four characters) of base64
|
||||
// data and writes up to three bytes to |out|. It sets |*out_num_bytes| to the
|
||||
// number of bytes written, which will be less than three if the quad ended
|
||||
// with padding. It returns one on success or zero on error.
|
||||
static int base64_decode_quad(uint8_t *out, size_t *out_num_bytes,
|
||||
const uint8_t *in) {
|
||||
const uint8_t a = base64_ascii_to_bin(in[0]);
|
||||
@@ -278,20 +300,20 @@ static int base64_decode_quad(uint8_t *out, size_t *out_num_bytes,
|
||||
|
||||
switch (padding_pattern) {
|
||||
case 0:
|
||||
/* The common case of no padding. */
|
||||
// The common case of no padding.
|
||||
*out_num_bytes = 3;
|
||||
out[0] = v >> 16;
|
||||
out[1] = v >> 8;
|
||||
out[2] = v;
|
||||
break;
|
||||
|
||||
case 1: /* xxx= */
|
||||
case 1: // xxx=
|
||||
*out_num_bytes = 2;
|
||||
out[0] = v >> 16;
|
||||
out[1] = v >> 8;
|
||||
break;
|
||||
|
||||
case 3: /* xx== */
|
||||
case 3: // xx==
|
||||
*out_num_bytes = 1;
|
||||
out[0] = v >> 16;
|
||||
break;
|
||||
@@ -322,7 +344,7 @@ int EVP_DecodeUpdate(EVP_ENCODE_CTX *ctx, uint8_t *out, int *out_len,
|
||||
continue;
|
||||
}
|
||||
|
||||
if (base64_ascii_to_bin(c) == 0xff || ctx->eof_seen) {
|
||||
if (ctx->eof_seen) {
|
||||
ctx->error_encountered = 1;
|
||||
return -1;
|
||||
}
|
||||
@@ -402,7 +424,7 @@ int EVP_DecodeBase64(uint8_t *out, size_t *out_len, size_t max_out,
|
||||
}
|
||||
|
||||
int EVP_DecodeBlock(uint8_t *dst, const uint8_t *src, size_t src_len) {
|
||||
/* Trim spaces and tabs from the beginning of the input. */
|
||||
// Trim spaces and tabs from the beginning of the input.
|
||||
while (src_len > 0) {
|
||||
if (src[0] != ' ' && src[0] != '\t') {
|
||||
break;
|
||||
@@ -412,7 +434,7 @@ int EVP_DecodeBlock(uint8_t *dst, const uint8_t *src, size_t src_len) {
|
||||
src_len--;
|
||||
}
|
||||
|
||||
/* Trim newlines, spaces and tabs from the end of the line. */
|
||||
// Trim newlines, spaces and tabs from the end of the line.
|
||||
while (src_len > 0) {
|
||||
switch (src[src_len-1]) {
|
||||
case ' ':
|
||||
@@ -433,8 +455,8 @@ int EVP_DecodeBlock(uint8_t *dst, const uint8_t *src, size_t src_len) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* EVP_DecodeBlock does not take padding into account, so put the
|
||||
* NULs back in... so the caller can strip them back out. */
|
||||
// EVP_DecodeBlock does not take padding into account, so put the
|
||||
// NULs back in... so the caller can strip them back out.
|
||||
while (dst_len % 3 != 0) {
|
||||
dst[dst_len++] = '\0';
|
||||
}
|
||||
|
||||
+164
-253
@@ -18,11 +18,14 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <openssl/base64.h>
|
||||
#include <openssl/crypto.h>
|
||||
#include <openssl/err.h>
|
||||
|
||||
#include "../internal.h"
|
||||
#include "../test/test_util.h"
|
||||
|
||||
|
||||
enum encoding_relation {
|
||||
@@ -100,7 +103,9 @@ static const TestVector kTestVectors[] = {
|
||||
"=======\n"},
|
||||
};
|
||||
|
||||
static const size_t kNumTests = OPENSSL_ARRAY_SIZE(kTestVectors);
|
||||
class Base64Test : public testing::TestWithParam<TestVector> {};
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(, Base64Test, testing::ValuesIn(kTestVectors));
|
||||
|
||||
// RemoveNewlines returns a copy of |in| with all '\n' characters removed.
|
||||
static std::string RemoveNewlines(const char *in) {
|
||||
@@ -116,281 +121,187 @@ static std::string RemoveNewlines(const char *in) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool TestEncodeBlock() {
|
||||
for (unsigned i = 0; i < kNumTests; i++) {
|
||||
const TestVector *t = &kTestVectors[i];
|
||||
if (t->relation != canonical) {
|
||||
continue;
|
||||
}
|
||||
TEST_P(Base64Test, EncodeBlock) {
|
||||
const TestVector &t = GetParam();
|
||||
if (t.relation != canonical) {
|
||||
return;
|
||||
}
|
||||
|
||||
const size_t decoded_len = strlen(t->decoded);
|
||||
const size_t decoded_len = strlen(t.decoded);
|
||||
size_t max_encoded_len;
|
||||
ASSERT_TRUE(EVP_EncodedLength(&max_encoded_len, decoded_len));
|
||||
|
||||
std::vector<uint8_t> out_vec(max_encoded_len);
|
||||
uint8_t *out = out_vec.data();
|
||||
size_t len = EVP_EncodeBlock(out, (const uint8_t *)t.decoded, decoded_len);
|
||||
|
||||
std::string encoded(RemoveNewlines(t.encoded));
|
||||
EXPECT_EQ(Bytes(encoded), Bytes(out, len));
|
||||
}
|
||||
|
||||
TEST_P(Base64Test, DecodeBase64) {
|
||||
const TestVector &t = GetParam();
|
||||
if (t.relation == valid) {
|
||||
// The non-canonical encodings will generally have odd whitespace etc
|
||||
// that |EVP_DecodeBase64| will reject.
|
||||
return;
|
||||
}
|
||||
|
||||
const std::string encoded(RemoveNewlines(t.encoded));
|
||||
std::vector<uint8_t> out_vec(encoded.size());
|
||||
uint8_t *out = out_vec.data();
|
||||
|
||||
size_t len;
|
||||
int ok = EVP_DecodeBase64(out, &len, out_vec.size(),
|
||||
(const uint8_t *)encoded.data(), encoded.size());
|
||||
|
||||
if (t.relation == invalid) {
|
||||
EXPECT_FALSE(ok);
|
||||
} else if (t.relation == canonical) {
|
||||
ASSERT_TRUE(ok);
|
||||
EXPECT_EQ(Bytes(t.decoded), Bytes(out, len));
|
||||
}
|
||||
}
|
||||
|
||||
TEST_P(Base64Test, DecodeBlock) {
|
||||
const TestVector &t = GetParam();
|
||||
if (t.relation != canonical) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::string encoded(RemoveNewlines(t.encoded));
|
||||
|
||||
std::vector<uint8_t> out_vec(encoded.size());
|
||||
uint8_t *out = out_vec.data();
|
||||
|
||||
// Test that the padding behavior of the deprecated API is preserved.
|
||||
int ret =
|
||||
EVP_DecodeBlock(out, (const uint8_t *)encoded.data(), encoded.size());
|
||||
ASSERT_GE(ret, 0);
|
||||
// EVP_DecodeBlock should ignore padding.
|
||||
ASSERT_EQ(0, ret % 3);
|
||||
size_t expected_len = strlen(t.decoded);
|
||||
if (expected_len % 3 != 0) {
|
||||
ret -= 3 - (expected_len % 3);
|
||||
}
|
||||
EXPECT_EQ(Bytes(t.decoded), Bytes(out, static_cast<size_t>(ret)));
|
||||
}
|
||||
|
||||
TEST_P(Base64Test, EncodeDecode) {
|
||||
const TestVector &t = GetParam();
|
||||
|
||||
EVP_ENCODE_CTX ctx;
|
||||
const size_t decoded_len = strlen(t.decoded);
|
||||
|
||||
if (t.relation == canonical) {
|
||||
size_t max_encoded_len;
|
||||
if (!EVP_EncodedLength(&max_encoded_len, decoded_len)) {
|
||||
fprintf(stderr, "#%u: EVP_EncodedLength failed\n", i);
|
||||
return false;
|
||||
}
|
||||
ASSERT_TRUE(EVP_EncodedLength(&max_encoded_len, decoded_len));
|
||||
|
||||
// EVP_EncodeUpdate will output new lines every 64 bytes of output so we
|
||||
// need slightly more than |EVP_EncodedLength| returns. */
|
||||
max_encoded_len += (max_encoded_len + 63) >> 6;
|
||||
std::vector<uint8_t> out_vec(max_encoded_len);
|
||||
uint8_t *out = out_vec.data();
|
||||
size_t len = EVP_EncodeBlock(out, (const uint8_t *)t->decoded, decoded_len);
|
||||
|
||||
std::string encoded(RemoveNewlines(t->encoded));
|
||||
if (len != encoded.size() ||
|
||||
OPENSSL_memcmp(out, encoded.data(), len) != 0) {
|
||||
fprintf(stderr, "encode(\"%s\") = \"%.*s\", want \"%s\"\n",
|
||||
t->decoded, (int)len, (const char*)out, encoded.c_str());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
EVP_EncodeInit(&ctx);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool TestDecodeBase64() {
|
||||
size_t len;
|
||||
|
||||
for (unsigned i = 0; i < kNumTests; i++) {
|
||||
const TestVector *t = &kTestVectors[i];
|
||||
|
||||
if (t->relation == valid) {
|
||||
// The non-canonical encodings will generally have odd whitespace etc
|
||||
// that |EVP_DecodeBase64| will reject.
|
||||
continue;
|
||||
}
|
||||
|
||||
const std::string encoded(RemoveNewlines(t->encoded));
|
||||
std::vector<uint8_t> out_vec(encoded.size());
|
||||
uint8_t *out = out_vec.data();
|
||||
|
||||
int ok = EVP_DecodeBase64(out, &len, out_vec.size(),
|
||||
(const uint8_t *)encoded.data(), encoded.size());
|
||||
|
||||
if (t->relation == invalid) {
|
||||
if (ok) {
|
||||
fprintf(stderr, "decode(\"%s\") didn't fail but should have\n",
|
||||
encoded.c_str());
|
||||
return false;
|
||||
}
|
||||
} else if (t->relation == canonical) {
|
||||
if (!ok) {
|
||||
fprintf(stderr, "decode(\"%s\") failed\n", encoded.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (len != strlen(t->decoded) ||
|
||||
OPENSSL_memcmp(out, t->decoded, len) != 0) {
|
||||
fprintf(stderr, "decode(\"%s\") = \"%.*s\", want \"%s\"\n",
|
||||
encoded.c_str(), (int)len, (const char*)out, t->decoded);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool TestDecodeBlock() {
|
||||
for (unsigned i = 0; i < kNumTests; i++) {
|
||||
const TestVector *t = &kTestVectors[i];
|
||||
if (t->relation != canonical) {
|
||||
continue;
|
||||
}
|
||||
|
||||
std::string encoded(RemoveNewlines(t->encoded));
|
||||
|
||||
std::vector<uint8_t> out_vec(encoded.size());
|
||||
uint8_t *out = out_vec.data();
|
||||
|
||||
// Test that the padding behavior of the deprecated API is preserved.
|
||||
int ret =
|
||||
EVP_DecodeBlock(out, (const uint8_t *)encoded.data(), encoded.size());
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "EVP_DecodeBlock(\"%s\") failed\n", t->encoded);
|
||||
return false;
|
||||
}
|
||||
if (ret % 3 != 0) {
|
||||
fprintf(stderr, "EVP_DecodeBlock did not ignore padding\n");
|
||||
return false;
|
||||
}
|
||||
size_t expected_len = strlen(t->decoded);
|
||||
if (expected_len % 3 != 0) {
|
||||
ret -= 3 - (expected_len % 3);
|
||||
}
|
||||
if (static_cast<size_t>(ret) != strlen(t->decoded) ||
|
||||
OPENSSL_memcmp(out, t->decoded, ret) != 0) {
|
||||
fprintf(stderr, "decode(\"%s\") = \"%.*s\", want \"%s\"\n",
|
||||
t->encoded, ret, (const char*)out, t->decoded);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool TestEncodeDecode() {
|
||||
for (unsigned test_num = 0; test_num < kNumTests; test_num++) {
|
||||
const TestVector *t = &kTestVectors[test_num];
|
||||
|
||||
EVP_ENCODE_CTX ctx;
|
||||
const size_t decoded_len = strlen(t->decoded);
|
||||
|
||||
if (t->relation == canonical) {
|
||||
size_t max_encoded_len;
|
||||
if (!EVP_EncodedLength(&max_encoded_len, decoded_len)) {
|
||||
fprintf(stderr, "#%u: EVP_EncodedLength failed\n", test_num);
|
||||
return false;
|
||||
}
|
||||
|
||||
// EVP_EncodeUpdate will output new lines every 64 bytes of output so we
|
||||
// need slightly more than |EVP_EncodedLength| returns. */
|
||||
max_encoded_len += (max_encoded_len + 63) >> 6;
|
||||
std::vector<uint8_t> out_vec(max_encoded_len);
|
||||
uint8_t *out = out_vec.data();
|
||||
|
||||
EVP_EncodeInit(&ctx);
|
||||
|
||||
int out_len;
|
||||
EVP_EncodeUpdate(&ctx, out, &out_len,
|
||||
reinterpret_cast<const uint8_t *>(t->decoded),
|
||||
decoded_len);
|
||||
size_t total = out_len;
|
||||
|
||||
EVP_EncodeFinal(&ctx, out + total, &out_len);
|
||||
total += out_len;
|
||||
|
||||
if (total != strlen(t->encoded) ||
|
||||
OPENSSL_memcmp(out, t->encoded, total) != 0) {
|
||||
fprintf(stderr, "#%u: EVP_EncodeUpdate produced different output: '%s' (%u)\n",
|
||||
test_num, out, static_cast<unsigned>(total));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<uint8_t> out_vec(strlen(t->encoded));
|
||||
uint8_t *out = out_vec.data();
|
||||
|
||||
EVP_DecodeInit(&ctx);
|
||||
int out_len;
|
||||
size_t total = 0;
|
||||
int ret = EVP_DecodeUpdate(&ctx, out, &out_len,
|
||||
reinterpret_cast<const uint8_t *>(t->encoded),
|
||||
strlen(t->encoded));
|
||||
if (ret != -1) {
|
||||
total = out_len;
|
||||
ret = EVP_DecodeFinal(&ctx, out + total, &out_len);
|
||||
total += out_len;
|
||||
}
|
||||
EVP_EncodeUpdate(&ctx, out, &out_len,
|
||||
reinterpret_cast<const uint8_t *>(t.decoded),
|
||||
decoded_len);
|
||||
size_t total = out_len;
|
||||
|
||||
switch (t->relation) {
|
||||
case canonical:
|
||||
case valid:
|
||||
if (ret == -1) {
|
||||
fprintf(stderr, "#%u: EVP_DecodeUpdate failed\n", test_num);
|
||||
return false;
|
||||
}
|
||||
if (total != decoded_len ||
|
||||
OPENSSL_memcmp(out, t->decoded, decoded_len)) {
|
||||
fprintf(stderr, "#%u: EVP_DecodeUpdate produced incorrect output\n",
|
||||
test_num);
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
EVP_EncodeFinal(&ctx, out + total, &out_len);
|
||||
total += out_len;
|
||||
|
||||
case invalid:
|
||||
if (ret != -1) {
|
||||
fprintf(stderr, "#%u: EVP_DecodeUpdate was successful but shouldn't have been\n", test_num);
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
EXPECT_EQ(Bytes(t.encoded), Bytes(out, total));
|
||||
}
|
||||
|
||||
return true;
|
||||
std::vector<uint8_t> out_vec(strlen(t.encoded));
|
||||
uint8_t *out = out_vec.data();
|
||||
|
||||
EVP_DecodeInit(&ctx);
|
||||
int out_len;
|
||||
size_t total = 0;
|
||||
int ret = EVP_DecodeUpdate(&ctx, out, &out_len,
|
||||
reinterpret_cast<const uint8_t *>(t.encoded),
|
||||
strlen(t.encoded));
|
||||
if (ret != -1) {
|
||||
total = out_len;
|
||||
ret = EVP_DecodeFinal(&ctx, out + total, &out_len);
|
||||
total += out_len;
|
||||
}
|
||||
|
||||
switch (t.relation) {
|
||||
case canonical:
|
||||
case valid:
|
||||
ASSERT_NE(-1, ret);
|
||||
EXPECT_EQ(Bytes(t.decoded), Bytes(out, total));
|
||||
break;
|
||||
|
||||
case invalid:
|
||||
EXPECT_EQ(-1, ret);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static bool TestDecodeUpdateStreaming() {
|
||||
for (unsigned test_num = 0; test_num < kNumTests; test_num++) {
|
||||
const TestVector *t = &kTestVectors[test_num];
|
||||
if (t->relation == invalid) {
|
||||
continue;
|
||||
}
|
||||
TEST_P(Base64Test, DecodeUpdateStreaming) {
|
||||
const TestVector &t = GetParam();
|
||||
if (t.relation == invalid) {
|
||||
return;
|
||||
}
|
||||
|
||||
const size_t encoded_len = strlen(t->encoded);
|
||||
const size_t encoded_len = strlen(t.encoded);
|
||||
|
||||
std::vector<uint8_t> out(encoded_len);
|
||||
std::vector<uint8_t> out(encoded_len);
|
||||
|
||||
for (size_t chunk_size = 1; chunk_size <= encoded_len; chunk_size++) {
|
||||
size_t out_len = 0;
|
||||
EVP_ENCODE_CTX ctx;
|
||||
EVP_DecodeInit(&ctx);
|
||||
for (size_t chunk_size = 1; chunk_size <= encoded_len; chunk_size++) {
|
||||
SCOPED_TRACE(chunk_size);
|
||||
size_t out_len = 0;
|
||||
EVP_ENCODE_CTX ctx;
|
||||
EVP_DecodeInit(&ctx);
|
||||
|
||||
for (size_t i = 0; i < encoded_len;) {
|
||||
size_t todo = encoded_len - i;
|
||||
if (todo > chunk_size) {
|
||||
todo = chunk_size;
|
||||
}
|
||||
|
||||
int bytes_written;
|
||||
int ret = EVP_DecodeUpdate(
|
||||
&ctx, out.data() + out_len, &bytes_written,
|
||||
reinterpret_cast<const uint8_t *>(t->encoded + i), todo);
|
||||
i += todo;
|
||||
|
||||
switch (ret) {
|
||||
case -1:
|
||||
fprintf(stderr, "#%u: EVP_DecodeUpdate returned error\n", test_num);
|
||||
return 0;
|
||||
case 0:
|
||||
out_len += bytes_written;
|
||||
if (i == encoded_len ||
|
||||
(i + 1 == encoded_len && t->encoded[i] == '\n') ||
|
||||
/* If there was an '-' in the input (which means “EOF”) then
|
||||
* this loop will continue to test that |EVP_DecodeUpdate| will
|
||||
* ignore the remainder of the input. */
|
||||
strchr(t->encoded, '-') != nullptr) {
|
||||
break;
|
||||
}
|
||||
|
||||
fprintf(stderr,
|
||||
"#%u: EVP_DecodeUpdate returned zero before end of "
|
||||
"encoded data\n",
|
||||
test_num);
|
||||
return 0;
|
||||
default:
|
||||
out_len += bytes_written;
|
||||
}
|
||||
for (size_t i = 0; i < encoded_len;) {
|
||||
size_t todo = encoded_len - i;
|
||||
if (todo > chunk_size) {
|
||||
todo = chunk_size;
|
||||
}
|
||||
|
||||
int bytes_written;
|
||||
int ret = EVP_DecodeFinal(&ctx, out.data() + out_len, &bytes_written);
|
||||
if (ret == -1) {
|
||||
fprintf(stderr, "#%u: EVP_DecodeFinal returned error\n", test_num);
|
||||
return 0;
|
||||
}
|
||||
out_len += bytes_written;
|
||||
int ret = EVP_DecodeUpdate(
|
||||
&ctx, out.data() + out_len, &bytes_written,
|
||||
reinterpret_cast<const uint8_t *>(t.encoded + i), todo);
|
||||
i += todo;
|
||||
|
||||
if (out_len != strlen(t->decoded) ||
|
||||
OPENSSL_memcmp(out.data(), t->decoded, out_len) != 0) {
|
||||
fprintf(stderr, "#%u: incorrect output\n", test_num);
|
||||
return 0;
|
||||
switch (ret) {
|
||||
case -1:
|
||||
FAIL() << "EVP_DecodeUpdate failed";
|
||||
case 0:
|
||||
out_len += bytes_written;
|
||||
if (i == encoded_len ||
|
||||
(i + 1 == encoded_len && t.encoded[i] == '\n') ||
|
||||
// If there was an '-' in the input (which means “EOF”) then
|
||||
// this loop will continue to test that |EVP_DecodeUpdate| will
|
||||
// ignore the remainder of the input.
|
||||
strchr(t.encoded, '-') != nullptr) {
|
||||
break;
|
||||
}
|
||||
|
||||
FAIL()
|
||||
<< "EVP_DecodeUpdate returned zero before end of encoded data.";
|
||||
case 1:
|
||||
out_len += bytes_written;
|
||||
break;
|
||||
default:
|
||||
FAIL() << "Invalid return value " << ret;
|
||||
}
|
||||
}
|
||||
|
||||
int bytes_written;
|
||||
int ret = EVP_DecodeFinal(&ctx, out.data() + out_len, &bytes_written);
|
||||
ASSERT_NE(ret, -1);
|
||||
out_len += bytes_written;
|
||||
|
||||
EXPECT_EQ(Bytes(t.decoded), Bytes(out.data(), out_len));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
CRYPTO_library_init();
|
||||
|
||||
if (!TestEncodeBlock() ||
|
||||
!TestDecodeBase64() ||
|
||||
!TestDecodeBlock() ||
|
||||
!TestDecodeUpdateStreaming() ||
|
||||
!TestEncodeDecode()) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("PASS\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -16,17 +16,3 @@ add_library(
|
||||
socket.c
|
||||
socket_helper.c
|
||||
)
|
||||
|
||||
add_executable(
|
||||
bio_test
|
||||
|
||||
bio_test.cc
|
||||
|
||||
$<TARGET_OBJECTS:test_support>
|
||||
)
|
||||
|
||||
target_link_libraries(bio_test crypto)
|
||||
if (WIN32)
|
||||
target_link_libraries(bio_test ws2_32)
|
||||
endif()
|
||||
add_dependencies(all_tests bio_test)
|
||||
|
||||
+55
-110
@@ -96,13 +96,6 @@ int BIO_free(BIO *bio) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (bio->callback != NULL) {
|
||||
int i = (int)bio->callback(bio, BIO_CB_FREE, NULL, 0, 0, 1);
|
||||
if (i <= 0) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
next_bio = BIO_pop(bio);
|
||||
|
||||
if (bio->method != NULL && bio->method->destroy != NULL) {
|
||||
@@ -127,64 +120,61 @@ void BIO_free_all(BIO *bio) {
|
||||
BIO_free(bio);
|
||||
}
|
||||
|
||||
static int bio_io(BIO *bio, void *buf, int len, size_t method_offset,
|
||||
int callback_flags, size_t *num) {
|
||||
int i;
|
||||
typedef int (*io_func_t)(BIO *, char *, int);
|
||||
io_func_t io_func = NULL;
|
||||
|
||||
if (bio != NULL && bio->method != NULL) {
|
||||
io_func =
|
||||
*((const io_func_t *)(((const uint8_t *)bio->method) + method_offset));
|
||||
}
|
||||
|
||||
if (io_func == NULL) {
|
||||
int BIO_read(BIO *bio, void *buf, int len) {
|
||||
if (bio == NULL || bio->method == NULL || bio->method->bread == NULL) {
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_R_UNSUPPORTED_METHOD);
|
||||
return -2;
|
||||
}
|
||||
|
||||
if (bio->callback != NULL) {
|
||||
i = (int) bio->callback(bio, callback_flags, buf, len, 0L, 1L);
|
||||
if (i <= 0) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
if (!bio->init) {
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_R_UNINITIALIZED);
|
||||
return -2;
|
||||
}
|
||||
|
||||
i = 0;
|
||||
if (buf != NULL && len > 0) {
|
||||
i = io_func(bio, buf, len);
|
||||
if (len <= 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (i > 0) {
|
||||
*num += i;
|
||||
int ret = bio->method->bread(bio, buf, len);
|
||||
if (ret > 0) {
|
||||
bio->num_read += ret;
|
||||
}
|
||||
|
||||
if (bio->callback != NULL) {
|
||||
i = (int)(bio->callback(bio, callback_flags | BIO_CB_RETURN, buf, len, 0L,
|
||||
(long)i));
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
int BIO_read(BIO *bio, void *buf, int len) {
|
||||
return bio_io(bio, buf, len, offsetof(BIO_METHOD, bread), BIO_CB_READ,
|
||||
&bio->num_read);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int BIO_gets(BIO *bio, char *buf, int len) {
|
||||
return bio_io(bio, buf, len, offsetof(BIO_METHOD, bgets), BIO_CB_GETS,
|
||||
&bio->num_read);
|
||||
if (bio == NULL || bio->method == NULL || bio->method->bgets == NULL) {
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_R_UNSUPPORTED_METHOD);
|
||||
return -2;
|
||||
}
|
||||
if (!bio->init) {
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_R_UNINITIALIZED);
|
||||
return -2;
|
||||
}
|
||||
if (len <= 0) {
|
||||
return 0;
|
||||
}
|
||||
int ret = bio->method->bgets(bio, buf, len);
|
||||
if (ret > 0) {
|
||||
bio->num_read += ret;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int BIO_write(BIO *bio, const void *in, int inl) {
|
||||
return bio_io(bio, (char *)in, inl, offsetof(BIO_METHOD, bwrite),
|
||||
BIO_CB_WRITE, &bio->num_write);
|
||||
if (bio == NULL || bio->method == NULL || bio->method->bwrite == NULL) {
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_R_UNSUPPORTED_METHOD);
|
||||
return -2;
|
||||
}
|
||||
if (!bio->init) {
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_R_UNINITIALIZED);
|
||||
return -2;
|
||||
}
|
||||
if (inl <= 0) {
|
||||
return 0;
|
||||
}
|
||||
int ret = bio->method->bwrite(bio, in, inl);
|
||||
if (ret > 0) {
|
||||
bio->num_write += ret;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int BIO_puts(BIO *bio, const char *in) {
|
||||
@@ -196,8 +186,6 @@ int BIO_flush(BIO *bio) {
|
||||
}
|
||||
|
||||
long BIO_ctrl(BIO *bio, int cmd, long larg, void *parg) {
|
||||
long ret;
|
||||
|
||||
if (bio == NULL) {
|
||||
return 0;
|
||||
}
|
||||
@@ -207,20 +195,7 @@ long BIO_ctrl(BIO *bio, int cmd, long larg, void *parg) {
|
||||
return -2;
|
||||
}
|
||||
|
||||
if (bio->callback != NULL) {
|
||||
ret = bio->callback(bio, BIO_CB_CTRL, parg, cmd, larg, 1);
|
||||
if (ret <= 0) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
ret = bio->method->ctrl(bio, cmd, larg, parg);
|
||||
|
||||
if (bio->callback != NULL) {
|
||||
ret = bio->callback(bio, BIO_CB_CTRL | BIO_CB_RETURN, parg, cmd, larg, ret);
|
||||
}
|
||||
|
||||
return ret;
|
||||
return bio->method->ctrl(bio, cmd, larg, parg);
|
||||
}
|
||||
|
||||
char *BIO_ptr_ctrl(BIO *b, int cmd, long larg) {
|
||||
@@ -305,9 +280,6 @@ void BIO_copy_next_retry(BIO *bio) {
|
||||
}
|
||||
|
||||
long BIO_callback_ctrl(BIO *bio, int cmd, bio_info_cb fp) {
|
||||
long ret;
|
||||
bio_info_cb cb;
|
||||
|
||||
if (bio == NULL) {
|
||||
return 0;
|
||||
}
|
||||
@@ -317,22 +289,7 @@ long BIO_callback_ctrl(BIO *bio, int cmd, bio_info_cb fp) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
cb = bio->callback;
|
||||
|
||||
if (cb != NULL) {
|
||||
ret = cb(bio, BIO_CB_CTRL, (void *)&fp, cmd, 0, 1L);
|
||||
if (ret <= 0) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
ret = bio->method->callback_ctrl(bio, cmd, fp);
|
||||
|
||||
if (cb != NULL) {
|
||||
ret = cb(bio, BIO_CB_CTRL | BIO_CB_RETURN, (void *)&fp, cmd, 0, ret);
|
||||
}
|
||||
|
||||
return ret;
|
||||
return bio->method->callback_ctrl(bio, cmd, fp);
|
||||
}
|
||||
|
||||
size_t BIO_pending(const BIO *bio) {
|
||||
@@ -363,18 +320,6 @@ int BIO_set_close(BIO *bio, int close_flag) {
|
||||
return BIO_ctrl(bio, BIO_CTRL_SET_CLOSE, close_flag, NULL);
|
||||
}
|
||||
|
||||
void BIO_set_callback(BIO *bio, bio_info_cb callback_func) {
|
||||
bio->callback = callback_func;
|
||||
}
|
||||
|
||||
void BIO_set_callback_arg(BIO *bio, char *arg) {
|
||||
bio->cb_arg = arg;
|
||||
}
|
||||
|
||||
char *BIO_get_callback_arg(const BIO *bio) {
|
||||
return bio->cb_arg;
|
||||
}
|
||||
|
||||
OPENSSL_EXPORT size_t BIO_number_read(const BIO *bio) {
|
||||
return bio->num_read;
|
||||
}
|
||||
@@ -464,14 +409,14 @@ void ERR_print_errors(BIO *bio) {
|
||||
ERR_print_errors_cb(print_bio, bio);
|
||||
}
|
||||
|
||||
/* bio_read_all reads everything from |bio| and prepends |prefix| to it. On
|
||||
* success, |*out| is set to an allocated buffer (which should be freed with
|
||||
* |OPENSSL_free|), |*out_len| is set to its length and one is returned. The
|
||||
* buffer will contain |prefix| followed by the contents of |bio|. On failure,
|
||||
* zero is returned.
|
||||
*
|
||||
* The function will fail if the size of the output would equal or exceed
|
||||
* |max_len|. */
|
||||
// bio_read_all reads everything from |bio| and prepends |prefix| to it. On
|
||||
// success, |*out| is set to an allocated buffer (which should be freed with
|
||||
// |OPENSSL_free|), |*out_len| is set to its length and one is returned. The
|
||||
// buffer will contain |prefix| followed by the contents of |bio|. On failure,
|
||||
// zero is returned.
|
||||
//
|
||||
// The function will fail if the size of the output would equal or exceed
|
||||
// |max_len|.
|
||||
static int bio_read_all(BIO *bio, uint8_t **out, size_t *out_len,
|
||||
const uint8_t *prefix, size_t prefix_len,
|
||||
size_t max_len) {
|
||||
@@ -535,20 +480,20 @@ int BIO_read_asn1(BIO *bio, uint8_t **out, size_t *out_len, size_t max_len) {
|
||||
const uint8_t length_byte = header[1];
|
||||
|
||||
if ((tag & 0x1f) == 0x1f) {
|
||||
/* Long form tags are not supported. */
|
||||
// Long form tags are not supported.
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t len, header_len;
|
||||
if ((length_byte & 0x80) == 0) {
|
||||
/* Short form length. */
|
||||
// Short form length.
|
||||
len = length_byte;
|
||||
header_len = kInitialHeaderLen;
|
||||
} else {
|
||||
const size_t num_bytes = length_byte & 0x7f;
|
||||
|
||||
if ((tag & 0x20 /* constructed */) != 0 && num_bytes == 0) {
|
||||
/* indefinite length. */
|
||||
// indefinite length.
|
||||
return bio_read_all(bio, out, out_len, header, kInitialHeaderLen,
|
||||
max_len);
|
||||
}
|
||||
@@ -571,12 +516,12 @@ int BIO_read_asn1(BIO *bio, uint8_t **out, size_t *out_len, size_t max_len) {
|
||||
}
|
||||
|
||||
if (len32 < 128) {
|
||||
/* Length should have used short-form encoding. */
|
||||
// Length should have used short-form encoding.
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((len32 >> ((num_bytes-1)*8)) == 0) {
|
||||
/* Length should have been at least one byte shorter. */
|
||||
// Length should have been at least one byte shorter.
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -82,16 +82,16 @@ BIO *BIO_new_mem_buf(const void *buf, int len) {
|
||||
}
|
||||
|
||||
b = (BUF_MEM *)ret->ptr;
|
||||
/* BIO_FLAGS_MEM_RDONLY ensures |b->data| is not written to. */
|
||||
// BIO_FLAGS_MEM_RDONLY ensures |b->data| is not written to.
|
||||
b->data = (void *)buf;
|
||||
b->length = size;
|
||||
b->max = size;
|
||||
|
||||
ret->flags |= BIO_FLAGS_MEM_RDONLY;
|
||||
|
||||
/* |num| is used to store the value that this BIO will return when it runs
|
||||
* out of data. If it's negative then the retry flags will also be set. Since
|
||||
* this is static data, retrying wont help */
|
||||
// |num| is used to store the value that this BIO will return when it runs
|
||||
// out of data. If it's negative then the retry flags will also be set. Since
|
||||
// this is static data, retrying wont help
|
||||
ret->num = 0;
|
||||
|
||||
return ret;
|
||||
@@ -105,8 +105,8 @@ static int mem_new(BIO *bio) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* |shutdown| is used to store the close flag: whether the BIO has ownership
|
||||
* of the BUF_MEM. */
|
||||
// |shutdown| is used to store the close flag: whether the BIO has ownership
|
||||
// of the BUF_MEM.
|
||||
bio->shutdown = 1;
|
||||
bio->init = 1;
|
||||
bio->num = -1;
|
||||
@@ -214,8 +214,8 @@ static int mem_gets(BIO *bio, char *buf, int size) {
|
||||
}
|
||||
}
|
||||
|
||||
/* i is now the max num of bytes to copy, either j or up to and including the
|
||||
* first newline */
|
||||
// i is now the max num of bytes to copy, either j or up to and including the
|
||||
// first newline
|
||||
|
||||
i = mem_read(bio, buf, i);
|
||||
if (i > 0) {
|
||||
@@ -233,7 +233,7 @@ static long mem_ctrl(BIO *bio, int cmd, long num, void *ptr) {
|
||||
switch (cmd) {
|
||||
case BIO_CTRL_RESET:
|
||||
if (b->data != NULL) {
|
||||
/* For read only case reset to the start again */
|
||||
// For read only case reset to the start again
|
||||
if (bio->flags & BIO_FLAGS_MEM_RDONLY) {
|
||||
b->data -= b->max - b->length;
|
||||
b->length = b->max;
|
||||
|
||||
+231
-326
@@ -16,7 +16,18 @@
|
||||
#define _POSIX_C_SOURCE 201410L
|
||||
#endif
|
||||
|
||||
#include <openssl/base.h>
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <openssl/bio.h>
|
||||
#include <openssl/crypto.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.h>
|
||||
|
||||
#include "../internal.h"
|
||||
#include "../test/test_util.h"
|
||||
|
||||
#if !defined(OPENSSL_WINDOWS)
|
||||
#include <arpa/inet.h>
|
||||
@@ -33,27 +44,15 @@ OPENSSL_MSVC_PRAGMA(warning(push, 3))
|
||||
OPENSSL_MSVC_PRAGMA(warning(pop))
|
||||
#endif
|
||||
|
||||
#include <openssl/bio.h>
|
||||
#include <openssl/crypto.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.h>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "../internal.h"
|
||||
|
||||
|
||||
#if !defined(OPENSSL_WINDOWS)
|
||||
static int closesocket(int sock) {
|
||||
return close(sock);
|
||||
}
|
||||
|
||||
static void PrintSocketError(const char *func) {
|
||||
perror(func);
|
||||
}
|
||||
static int closesocket(int sock) { return close(sock); }
|
||||
static std::string LastSocketError() { return strerror(errno); }
|
||||
#else
|
||||
static void PrintSocketError(const char *func) {
|
||||
fprintf(stderr, "%s: %d\n", func, WSAGetLastError());
|
||||
static std::string LastSocketError() {
|
||||
char buf[DECIMAL_SIZE(int) + 1];
|
||||
BIO_snprintf(buf, sizeof(buf), "%d", WSAGetLastError());
|
||||
return buf;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -68,356 +67,262 @@ class ScopedSocket {
|
||||
const int sock_;
|
||||
};
|
||||
|
||||
static bool TestSocketConnect() {
|
||||
TEST(BIOTest, SocketConnect) {
|
||||
static const char kTestMessage[] = "test";
|
||||
int listening_sock = -1;
|
||||
socklen_t len = 0;
|
||||
sockaddr_storage ss;
|
||||
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) &ss;
|
||||
struct sockaddr_in *sin = (struct sockaddr_in *) &ss;
|
||||
OPENSSL_memset(&ss, 0, sizeof(ss));
|
||||
|
||||
int listening_sock = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (listening_sock == -1) {
|
||||
PrintSocketError("socket");
|
||||
return false;
|
||||
ss.ss_family = AF_INET6;
|
||||
listening_sock = socket(AF_INET6, SOCK_STREAM, 0);
|
||||
ASSERT_NE(-1, listening_sock) << LastSocketError();
|
||||
len = sizeof(*sin6);
|
||||
ASSERT_EQ(1, inet_pton(AF_INET6, "::1", &sin6->sin6_addr))
|
||||
<< LastSocketError();
|
||||
if (bind(listening_sock, (struct sockaddr *)sin6, sizeof(*sin6)) == -1) {
|
||||
closesocket(listening_sock);
|
||||
|
||||
ss.ss_family = AF_INET;
|
||||
listening_sock = socket(AF_INET, SOCK_STREAM, 0);
|
||||
ASSERT_NE(-1, listening_sock) << LastSocketError();
|
||||
len = sizeof(*sin);
|
||||
ASSERT_EQ(1, inet_pton(AF_INET, "127.0.0.1", &sin->sin_addr))
|
||||
<< LastSocketError();
|
||||
ASSERT_EQ(0, bind(listening_sock, (struct sockaddr *)sin, sizeof(*sin)))
|
||||
<< LastSocketError();
|
||||
}
|
||||
|
||||
ScopedSocket listening_sock_closer(listening_sock);
|
||||
|
||||
struct sockaddr_in sin;
|
||||
OPENSSL_memset(&sin, 0, sizeof(sin));
|
||||
sin.sin_family = AF_INET;
|
||||
if (!inet_pton(AF_INET, "127.0.0.1", &sin.sin_addr)) {
|
||||
PrintSocketError("inet_pton");
|
||||
return false;
|
||||
}
|
||||
if (bind(listening_sock, (struct sockaddr *)&sin, sizeof(sin)) != 0) {
|
||||
PrintSocketError("bind");
|
||||
return false;
|
||||
}
|
||||
if (listen(listening_sock, 1)) {
|
||||
PrintSocketError("listen");
|
||||
return false;
|
||||
}
|
||||
socklen_t sockaddr_len = sizeof(sin);
|
||||
if (getsockname(listening_sock, (struct sockaddr *)&sin, &sockaddr_len) ||
|
||||
sockaddr_len != sizeof(sin)) {
|
||||
PrintSocketError("getsockname");
|
||||
return false;
|
||||
}
|
||||
ASSERT_EQ(0, listen(listening_sock, 1)) << LastSocketError();
|
||||
ASSERT_EQ(0, getsockname(listening_sock, (struct sockaddr *)&ss, &len))
|
||||
<< LastSocketError();
|
||||
|
||||
char hostname[80];
|
||||
BIO_snprintf(hostname, sizeof(hostname), "%s:%d", "127.0.0.1",
|
||||
ntohs(sin.sin_port));
|
||||
if (ss.ss_family == AF_INET6) {
|
||||
BIO_snprintf(hostname, sizeof(hostname), "[::1]:%d",
|
||||
ntohs(sin6->sin6_port));
|
||||
} else if (ss.ss_family == AF_INET) {
|
||||
BIO_snprintf(hostname, sizeof(hostname), "127.0.0.1:%d",
|
||||
ntohs(sin->sin_port));
|
||||
}
|
||||
|
||||
// Connect to it with a connect BIO.
|
||||
bssl::UniquePtr<BIO> bio(BIO_new_connect(hostname));
|
||||
if (!bio) {
|
||||
fprintf(stderr, "BIO_new_connect failed.\n");
|
||||
return false;
|
||||
}
|
||||
ASSERT_TRUE(bio);
|
||||
|
||||
if (BIO_write(bio.get(), kTestMessage, sizeof(kTestMessage)) !=
|
||||
sizeof(kTestMessage)) {
|
||||
fprintf(stderr, "BIO_write failed.\n");
|
||||
ERR_print_errors_fp(stderr);
|
||||
return false;
|
||||
}
|
||||
// Write a test message to the BIO.
|
||||
ASSERT_EQ(static_cast<int>(sizeof(kTestMessage)),
|
||||
BIO_write(bio.get(), kTestMessage, sizeof(kTestMessage)));
|
||||
|
||||
int sock = accept(listening_sock, (struct sockaddr *) &sin, &sockaddr_len);
|
||||
if (sock == -1) {
|
||||
PrintSocketError("accept");
|
||||
return false;
|
||||
}
|
||||
// Accept the socket.
|
||||
int sock = accept(listening_sock, (struct sockaddr *) &ss, &len);
|
||||
ASSERT_NE(-1, sock) << LastSocketError();
|
||||
ScopedSocket sock_closer(sock);
|
||||
|
||||
char buf[5];
|
||||
if (recv(sock, buf, sizeof(buf), 0) != sizeof(kTestMessage)) {
|
||||
PrintSocketError("read");
|
||||
return false;
|
||||
}
|
||||
if (OPENSSL_memcmp(buf, kTestMessage, sizeof(kTestMessage))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
// Check the same message is read back out.
|
||||
char buf[sizeof(kTestMessage)];
|
||||
ASSERT_EQ(static_cast<int>(sizeof(kTestMessage)),
|
||||
recv(sock, buf, sizeof(buf), 0))
|
||||
<< LastSocketError();
|
||||
EXPECT_EQ(Bytes(kTestMessage, sizeof(kTestMessage)), Bytes(buf, sizeof(buf)));
|
||||
}
|
||||
|
||||
static bool TestPrintf() {
|
||||
TEST(BIOTest, Printf) {
|
||||
// Test a short output, a very long one, and various sizes around
|
||||
// 256 (the size of the buffer) to ensure edge cases are correct.
|
||||
static const size_t kLengths[] = { 5, 250, 251, 252, 253, 254, 1023 };
|
||||
static const size_t kLengths[] = {5, 250, 251, 252, 253, 254, 1023};
|
||||
|
||||
bssl::UniquePtr<BIO> bio(BIO_new(BIO_s_mem()));
|
||||
if (!bio) {
|
||||
fprintf(stderr, "BIO_new failed\n");
|
||||
return false;
|
||||
}
|
||||
ASSERT_TRUE(bio);
|
||||
|
||||
for (size_t i = 0; i < OPENSSL_ARRAY_SIZE(kLengths); i++) {
|
||||
char string[1024];
|
||||
if (kLengths[i] >= sizeof(string)) {
|
||||
fprintf(stderr, "Bad test string length\n");
|
||||
return false;
|
||||
}
|
||||
OPENSSL_memset(string, 'a', sizeof(string));
|
||||
string[kLengths[i]] = '\0';
|
||||
for (size_t length : kLengths) {
|
||||
SCOPED_TRACE(length);
|
||||
|
||||
std::string in(length, 'a');
|
||||
|
||||
int ret = BIO_printf(bio.get(), "test %s", in.c_str());
|
||||
ASSERT_GE(ret, 0);
|
||||
EXPECT_EQ(5 + length, static_cast<size_t>(ret));
|
||||
|
||||
int ret = BIO_printf(bio.get(), "test %s", string);
|
||||
if (ret < 0 || static_cast<size_t>(ret) != 5 + kLengths[i]) {
|
||||
fprintf(stderr, "BIO_printf failed: %d\n", ret);
|
||||
return false;
|
||||
}
|
||||
const uint8_t *contents;
|
||||
size_t len;
|
||||
if (!BIO_mem_contents(bio.get(), &contents, &len)) {
|
||||
fprintf(stderr, "BIO_mem_contents failed\n");
|
||||
return false;
|
||||
}
|
||||
if (len != 5 + kLengths[i] ||
|
||||
strncmp((const char *)contents, "test ", 5) != 0 ||
|
||||
strncmp((const char *)contents + 5, string, kLengths[i]) != 0) {
|
||||
fprintf(stderr, "Contents did not match: %.*s\n", (int)len, contents);
|
||||
return false;
|
||||
}
|
||||
ASSERT_TRUE(BIO_mem_contents(bio.get(), &contents, &len));
|
||||
EXPECT_EQ("test " + in,
|
||||
std::string(reinterpret_cast<const char *>(contents), len));
|
||||
|
||||
if (!BIO_reset(bio.get())) {
|
||||
fprintf(stderr, "BIO_reset failed\n");
|
||||
return false;
|
||||
}
|
||||
ASSERT_TRUE(BIO_reset(bio.get()));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool ReadASN1(bool should_succeed, const uint8_t *data, size_t data_len,
|
||||
size_t expected_len, size_t max_len) {
|
||||
bssl::UniquePtr<BIO> bio(BIO_new_mem_buf(data, data_len));
|
||||
static const size_t kLargeASN1PayloadLen = 8000;
|
||||
|
||||
struct ASN1TestParam {
|
||||
bool should_succeed;
|
||||
std::vector<uint8_t> input;
|
||||
// suffix_len is the number of zeros to append to |input|.
|
||||
size_t suffix_len;
|
||||
// expected_len, if |should_succeed| is true, is the expected length of the
|
||||
// ASN.1 element.
|
||||
size_t expected_len;
|
||||
size_t max_len;
|
||||
} kASN1TestParams[] = {
|
||||
{true, {0x30, 2, 1, 2, 0, 0}, 0, 4, 100},
|
||||
{false /* truncated */, {0x30, 3, 1, 2}, 0, 0, 100},
|
||||
{false /* should be short len */, {0x30, 0x81, 1, 1}, 0, 0, 100},
|
||||
{false /* zero padded */, {0x30, 0x82, 0, 1, 1}, 0, 0, 100},
|
||||
|
||||
// Test a large payload.
|
||||
{true,
|
||||
{0x30, 0x82, kLargeASN1PayloadLen >> 8, kLargeASN1PayloadLen & 0xff},
|
||||
kLargeASN1PayloadLen,
|
||||
4 + kLargeASN1PayloadLen,
|
||||
kLargeASN1PayloadLen * 2},
|
||||
{false /* max_len too short */,
|
||||
{0x30, 0x82, kLargeASN1PayloadLen >> 8, kLargeASN1PayloadLen & 0xff},
|
||||
kLargeASN1PayloadLen,
|
||||
4 + kLargeASN1PayloadLen,
|
||||
3 + kLargeASN1PayloadLen},
|
||||
|
||||
// Test an indefinite-length input.
|
||||
{true,
|
||||
{0x30, 0x80},
|
||||
kLargeASN1PayloadLen + 2,
|
||||
2 + kLargeASN1PayloadLen + 2,
|
||||
kLargeASN1PayloadLen * 2},
|
||||
{false /* max_len too short */,
|
||||
{0x30, 0x80},
|
||||
kLargeASN1PayloadLen + 2,
|
||||
2 + kLargeASN1PayloadLen + 2,
|
||||
2 + kLargeASN1PayloadLen + 1},
|
||||
};
|
||||
|
||||
class BIOASN1Test : public testing::TestWithParam<ASN1TestParam> {};
|
||||
|
||||
TEST_P(BIOASN1Test, ReadASN1) {
|
||||
const ASN1TestParam& param = GetParam();
|
||||
std::vector<uint8_t> input = param.input;
|
||||
input.resize(input.size() + param.suffix_len, 0);
|
||||
|
||||
bssl::UniquePtr<BIO> bio(BIO_new_mem_buf(input.data(), input.size()));
|
||||
ASSERT_TRUE(bio);
|
||||
|
||||
uint8_t *out;
|
||||
size_t out_len;
|
||||
int ok = BIO_read_asn1(bio.get(), &out, &out_len, max_len);
|
||||
int ok = BIO_read_asn1(bio.get(), &out, &out_len, param.max_len);
|
||||
if (!ok) {
|
||||
out = nullptr;
|
||||
}
|
||||
bssl::UniquePtr<uint8_t> out_storage(out);
|
||||
|
||||
if (should_succeed != (ok == 1)) {
|
||||
return false;
|
||||
ASSERT_EQ(param.should_succeed, (ok == 1));
|
||||
if (param.should_succeed) {
|
||||
EXPECT_EQ(Bytes(input.data(), param.expected_len), Bytes(out, out_len));
|
||||
}
|
||||
|
||||
if (should_succeed && (out_len != expected_len ||
|
||||
OPENSSL_memcmp(data, out, expected_len) != 0)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool TestASN1() {
|
||||
static const uint8_t kData1[] = {0x30, 2, 1, 2, 0, 0};
|
||||
static const uint8_t kData2[] = {0x30, 3, 1, 2}; /* truncated */
|
||||
static const uint8_t kData3[] = {0x30, 0x81, 1, 1}; /* should be short len */
|
||||
static const uint8_t kData4[] = {0x30, 0x82, 0, 1, 1}; /* zero padded. */
|
||||
INSTANTIATE_TEST_CASE_P(, BIOASN1Test, testing::ValuesIn(kASN1TestParams));
|
||||
|
||||
if (!ReadASN1(true, kData1, sizeof(kData1), 4, 100) ||
|
||||
!ReadASN1(false, kData2, sizeof(kData2), 0, 100) ||
|
||||
!ReadASN1(false, kData3, sizeof(kData3), 0, 100) ||
|
||||
!ReadASN1(false, kData4, sizeof(kData4), 0, 100)) {
|
||||
return false;
|
||||
// Run through the tests twice, swapping |bio1| and |bio2|, for symmetry.
|
||||
class BIOPairTest : public testing::TestWithParam<bool> {};
|
||||
|
||||
TEST_P(BIOPairTest, TestPair) {
|
||||
BIO *bio1, *bio2;
|
||||
ASSERT_TRUE(BIO_new_bio_pair(&bio1, 10, &bio2, 10));
|
||||
bssl::UniquePtr<BIO> free_bio1(bio1), free_bio2(bio2);
|
||||
|
||||
if (GetParam()) {
|
||||
std::swap(bio1, bio2);
|
||||
}
|
||||
|
||||
static const size_t kLargePayloadLen = 8000;
|
||||
static const uint8_t kLargePrefix[] = {0x30, 0x82, kLargePayloadLen >> 8,
|
||||
kLargePayloadLen & 0xff};
|
||||
bssl::UniquePtr<uint8_t> large(reinterpret_cast<uint8_t *>(
|
||||
OPENSSL_malloc(sizeof(kLargePrefix) + kLargePayloadLen)));
|
||||
if (!large) {
|
||||
return false;
|
||||
}
|
||||
OPENSSL_memset(large.get() + sizeof(kLargePrefix), 0, kLargePayloadLen);
|
||||
OPENSSL_memcpy(large.get(), kLargePrefix, sizeof(kLargePrefix));
|
||||
// Check initial states.
|
||||
EXPECT_EQ(10u, BIO_ctrl_get_write_guarantee(bio1));
|
||||
EXPECT_EQ(0u, BIO_ctrl_get_read_request(bio1));
|
||||
|
||||
if (!ReadASN1(true, large.get(), sizeof(kLargePrefix) + kLargePayloadLen,
|
||||
sizeof(kLargePrefix) + kLargePayloadLen,
|
||||
kLargePayloadLen * 2)) {
|
||||
fprintf(stderr, "Large payload test failed.\n");
|
||||
return false;
|
||||
}
|
||||
// Data written in one end may be read out the other.
|
||||
uint8_t buf[20];
|
||||
EXPECT_EQ(5, BIO_write(bio1, "12345", 5));
|
||||
EXPECT_EQ(5u, BIO_ctrl_get_write_guarantee(bio1));
|
||||
ASSERT_EQ(5, BIO_read(bio2, buf, sizeof(buf)));
|
||||
EXPECT_EQ(Bytes("12345"), Bytes(buf, 5));
|
||||
EXPECT_EQ(10u, BIO_ctrl_get_write_guarantee(bio1));
|
||||
|
||||
if (!ReadASN1(false, large.get(), sizeof(kLargePrefix) + kLargePayloadLen,
|
||||
sizeof(kLargePrefix) + kLargePayloadLen,
|
||||
kLargePayloadLen - 1)) {
|
||||
fprintf(stderr, "max_len test failed.\n");
|
||||
return false;
|
||||
}
|
||||
// Attempting to write more than 10 bytes will write partially.
|
||||
EXPECT_EQ(10, BIO_write(bio1, "1234567890___", 13));
|
||||
EXPECT_EQ(0u, BIO_ctrl_get_write_guarantee(bio1));
|
||||
EXPECT_EQ(-1, BIO_write(bio1, "z", 1));
|
||||
EXPECT_TRUE(BIO_should_write(bio1));
|
||||
ASSERT_EQ(10, BIO_read(bio2, buf, sizeof(buf)));
|
||||
EXPECT_EQ(Bytes("1234567890"), Bytes(buf, 10));
|
||||
EXPECT_EQ(10u, BIO_ctrl_get_write_guarantee(bio1));
|
||||
|
||||
static const uint8_t kIndefPrefix[] = {0x30, 0x80};
|
||||
OPENSSL_memcpy(large.get(), kIndefPrefix, sizeof(kIndefPrefix));
|
||||
if (!ReadASN1(true, large.get(), sizeof(kLargePrefix) + kLargePayloadLen,
|
||||
sizeof(kLargePrefix) + kLargePayloadLen,
|
||||
kLargePayloadLen*2)) {
|
||||
fprintf(stderr, "indefinite length test failed.\n");
|
||||
return false;
|
||||
}
|
||||
// Unsuccessful reads update the read request.
|
||||
EXPECT_EQ(-1, BIO_read(bio2, buf, 5));
|
||||
EXPECT_TRUE(BIO_should_read(bio2));
|
||||
EXPECT_EQ(5u, BIO_ctrl_get_read_request(bio1));
|
||||
|
||||
if (!ReadASN1(false, large.get(), sizeof(kLargePrefix) + kLargePayloadLen,
|
||||
sizeof(kLargePrefix) + kLargePayloadLen,
|
||||
kLargePayloadLen-1)) {
|
||||
fprintf(stderr, "indefinite length, max_len test failed.\n");
|
||||
return false;
|
||||
}
|
||||
// The read request is clamped to the size of the buffer.
|
||||
EXPECT_EQ(-1, BIO_read(bio2, buf, 20));
|
||||
EXPECT_TRUE(BIO_should_read(bio2));
|
||||
EXPECT_EQ(10u, BIO_ctrl_get_read_request(bio1));
|
||||
|
||||
return true;
|
||||
// Data may be written and read in chunks.
|
||||
EXPECT_EQ(5, BIO_write(bio1, "12345", 5));
|
||||
EXPECT_EQ(5u, BIO_ctrl_get_write_guarantee(bio1));
|
||||
EXPECT_EQ(5, BIO_write(bio1, "67890___", 8));
|
||||
EXPECT_EQ(0u, BIO_ctrl_get_write_guarantee(bio1));
|
||||
ASSERT_EQ(3, BIO_read(bio2, buf, 3));
|
||||
EXPECT_EQ(Bytes("123"), Bytes(buf, 3));
|
||||
EXPECT_EQ(3u, BIO_ctrl_get_write_guarantee(bio1));
|
||||
ASSERT_EQ(7, BIO_read(bio2, buf, sizeof(buf)));
|
||||
EXPECT_EQ(Bytes("4567890"), Bytes(buf, 7));
|
||||
EXPECT_EQ(10u, BIO_ctrl_get_write_guarantee(bio1));
|
||||
|
||||
// Successful reads reset the read request.
|
||||
EXPECT_EQ(0u, BIO_ctrl_get_read_request(bio1));
|
||||
|
||||
// Test writes and reads starting in the middle of the ring buffer and
|
||||
// wrapping to front.
|
||||
EXPECT_EQ(8, BIO_write(bio1, "abcdefgh", 8));
|
||||
EXPECT_EQ(2u, BIO_ctrl_get_write_guarantee(bio1));
|
||||
ASSERT_EQ(3, BIO_read(bio2, buf, 3));
|
||||
EXPECT_EQ(Bytes("abc"), Bytes(buf, 3));
|
||||
EXPECT_EQ(5u, BIO_ctrl_get_write_guarantee(bio1));
|
||||
EXPECT_EQ(5, BIO_write(bio1, "ijklm___", 8));
|
||||
EXPECT_EQ(0u, BIO_ctrl_get_write_guarantee(bio1));
|
||||
ASSERT_EQ(10, BIO_read(bio2, buf, sizeof(buf)));
|
||||
EXPECT_EQ(Bytes("defghijklm"), Bytes(buf, 10));
|
||||
EXPECT_EQ(10u, BIO_ctrl_get_write_guarantee(bio1));
|
||||
|
||||
// Data may flow from both ends in parallel.
|
||||
EXPECT_EQ(5, BIO_write(bio1, "12345", 5));
|
||||
EXPECT_EQ(5, BIO_write(bio2, "67890", 5));
|
||||
ASSERT_EQ(5, BIO_read(bio2, buf, sizeof(buf)));
|
||||
EXPECT_EQ(Bytes("12345"), Bytes(buf, 5));
|
||||
ASSERT_EQ(5, BIO_read(bio1, buf, sizeof(buf)));
|
||||
EXPECT_EQ(Bytes("67890"), Bytes(buf, 5));
|
||||
|
||||
// Closing the write end causes an EOF on the read half, after draining.
|
||||
EXPECT_EQ(5, BIO_write(bio1, "12345", 5));
|
||||
EXPECT_TRUE(BIO_shutdown_wr(bio1));
|
||||
ASSERT_EQ(5, BIO_read(bio2, buf, sizeof(buf)));
|
||||
EXPECT_EQ(Bytes("12345"), Bytes(buf, 5));
|
||||
EXPECT_EQ(0, BIO_read(bio2, buf, sizeof(buf)));
|
||||
|
||||
// A closed write end may not be written to.
|
||||
EXPECT_EQ(0u, BIO_ctrl_get_write_guarantee(bio1));
|
||||
EXPECT_EQ(-1, BIO_write(bio1, "_____", 5));
|
||||
|
||||
uint32_t err = ERR_get_error();
|
||||
EXPECT_EQ(ERR_LIB_BIO, ERR_GET_LIB(err));
|
||||
EXPECT_EQ(BIO_R_BROKEN_PIPE, ERR_GET_REASON(err));
|
||||
|
||||
// The other end is still functional.
|
||||
EXPECT_EQ(5, BIO_write(bio2, "12345", 5));
|
||||
ASSERT_EQ(5, BIO_read(bio1, buf, sizeof(buf)));
|
||||
EXPECT_EQ(Bytes("12345"), Bytes(buf, 5));
|
||||
}
|
||||
|
||||
static bool TestPair() {
|
||||
// Run through the tests twice, swapping |bio1| and |bio2|, for symmetry.
|
||||
for (int i = 0; i < 2; i++) {
|
||||
BIO *bio1, *bio2;
|
||||
if (!BIO_new_bio_pair(&bio1, 10, &bio2, 10)) {
|
||||
return false;
|
||||
}
|
||||
bssl::UniquePtr<BIO> free_bio1(bio1), free_bio2(bio2);
|
||||
|
||||
if (i == 1) {
|
||||
std::swap(bio1, bio2);
|
||||
}
|
||||
|
||||
// Check initial states.
|
||||
if (BIO_ctrl_get_write_guarantee(bio1) != 10 ||
|
||||
BIO_ctrl_get_read_request(bio1) != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Data written in one end may be read out the other.
|
||||
char buf[20];
|
||||
if (BIO_write(bio1, "12345", 5) != 5 ||
|
||||
BIO_ctrl_get_write_guarantee(bio1) != 5 ||
|
||||
BIO_read(bio2, buf, sizeof(buf)) != 5 ||
|
||||
OPENSSL_memcmp(buf, "12345", 5) != 0 ||
|
||||
BIO_ctrl_get_write_guarantee(bio1) != 10) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Attempting to write more than 10 bytes will write partially.
|
||||
if (BIO_write(bio1, "1234567890___", 13) != 10 ||
|
||||
BIO_ctrl_get_write_guarantee(bio1) != 0 ||
|
||||
BIO_write(bio1, "z", 1) != -1 ||
|
||||
!BIO_should_write(bio1) ||
|
||||
BIO_read(bio2, buf, sizeof(buf)) != 10 ||
|
||||
OPENSSL_memcmp(buf, "1234567890", 10) != 0 ||
|
||||
BIO_ctrl_get_write_guarantee(bio1) != 10) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Unsuccessful reads update the read request.
|
||||
if (BIO_read(bio2, buf, 5) != -1 ||
|
||||
!BIO_should_read(bio2) ||
|
||||
BIO_ctrl_get_read_request(bio1) != 5) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// The read request is clamped to the size of the buffer.
|
||||
if (BIO_read(bio2, buf, 20) != -1 ||
|
||||
!BIO_should_read(bio2) ||
|
||||
BIO_ctrl_get_read_request(bio1) != 10) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Data may be written and read in chunks.
|
||||
if (BIO_write(bio1, "12345", 5) != 5 ||
|
||||
BIO_ctrl_get_write_guarantee(bio1) != 5 ||
|
||||
BIO_write(bio1, "67890___", 8) != 5 ||
|
||||
BIO_ctrl_get_write_guarantee(bio1) != 0 ||
|
||||
BIO_read(bio2, buf, 3) != 3 ||
|
||||
OPENSSL_memcmp(buf, "123", 3) != 0 ||
|
||||
BIO_ctrl_get_write_guarantee(bio1) != 3 ||
|
||||
BIO_read(bio2, buf, sizeof(buf)) != 7 ||
|
||||
OPENSSL_memcmp(buf, "4567890", 7) != 0 ||
|
||||
BIO_ctrl_get_write_guarantee(bio1) != 10) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Successful reads reset the read request.
|
||||
if (BIO_ctrl_get_read_request(bio1) != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Test writes and reads starting in the middle of the ring buffer and
|
||||
// wrapping to front.
|
||||
if (BIO_write(bio1, "abcdefgh", 8) != 8 ||
|
||||
BIO_ctrl_get_write_guarantee(bio1) != 2 ||
|
||||
BIO_read(bio2, buf, 3) != 3 ||
|
||||
OPENSSL_memcmp(buf, "abc", 3) != 0 ||
|
||||
BIO_ctrl_get_write_guarantee(bio1) != 5 ||
|
||||
BIO_write(bio1, "ijklm___", 8) != 5 ||
|
||||
BIO_ctrl_get_write_guarantee(bio1) != 0 ||
|
||||
BIO_read(bio2, buf, sizeof(buf)) != 10 ||
|
||||
OPENSSL_memcmp(buf, "defghijklm", 10) != 0 ||
|
||||
BIO_ctrl_get_write_guarantee(bio1) != 10) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Data may flow from both ends in parallel.
|
||||
if (BIO_write(bio1, "12345", 5) != 5 ||
|
||||
BIO_write(bio2, "67890", 5) != 5 ||
|
||||
BIO_read(bio2, buf, sizeof(buf)) != 5 ||
|
||||
OPENSSL_memcmp(buf, "12345", 5) != 0 ||
|
||||
BIO_read(bio1, buf, sizeof(buf)) != 5 ||
|
||||
OPENSSL_memcmp(buf, "67890", 5) != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Closing the write end causes an EOF on the read half, after draining.
|
||||
if (BIO_write(bio1, "12345", 5) != 5 ||
|
||||
!BIO_shutdown_wr(bio1) ||
|
||||
BIO_read(bio2, buf, sizeof(buf)) != 5 ||
|
||||
OPENSSL_memcmp(buf, "12345", 5) != 0 ||
|
||||
BIO_read(bio2, buf, sizeof(buf)) != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// A closed write end may not be written to.
|
||||
if (BIO_ctrl_get_write_guarantee(bio1) != 0 ||
|
||||
BIO_write(bio1, "_____", 5) != -1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t err = ERR_get_error();
|
||||
if (ERR_GET_LIB(err) != ERR_LIB_BIO ||
|
||||
ERR_GET_REASON(err) != BIO_R_BROKEN_PIPE) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// The other end is still functional.
|
||||
if (BIO_write(bio2, "12345", 5) != 5 ||
|
||||
BIO_read(bio1, buf, sizeof(buf)) != 5 ||
|
||||
OPENSSL_memcmp(buf, "12345", 5) != 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main() {
|
||||
CRYPTO_library_init();
|
||||
|
||||
#if defined(OPENSSL_WINDOWS)
|
||||
// Initialize Winsock.
|
||||
WORD wsa_version = MAKEWORD(2, 2);
|
||||
WSADATA wsa_data;
|
||||
int wsa_err = WSAStartup(wsa_version, &wsa_data);
|
||||
if (wsa_err != 0) {
|
||||
fprintf(stderr, "WSAStartup failed: %d\n", wsa_err);
|
||||
return 1;
|
||||
}
|
||||
if (wsa_data.wVersion != wsa_version) {
|
||||
fprintf(stderr, "Didn't get expected version: %x\n", wsa_data.wVersion);
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!TestSocketConnect() ||
|
||||
!TestPrintf() ||
|
||||
!TestASN1() ||
|
||||
!TestPair()) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("PASS\n");
|
||||
return 0;
|
||||
}
|
||||
INSTANTIATE_TEST_CASE_P(, BIOPairTest, testing::Values(false, true));
|
||||
|
||||
+17
-17
@@ -98,12 +98,12 @@ typedef struct bio_connect_st {
|
||||
struct sockaddr_storage them;
|
||||
socklen_t them_length;
|
||||
|
||||
/* the file descriptor is kept in bio->num in order to match the socket
|
||||
* BIO. */
|
||||
// the file descriptor is kept in bio->num in order to match the socket
|
||||
// BIO.
|
||||
|
||||
/* info_callback is called when the connection is initially made
|
||||
* callback(BIO,state,ret); The callback should return 'ret', state is for
|
||||
* compatibility with the SSL info_callback. */
|
||||
// info_callback is called when the connection is initially made
|
||||
// callback(BIO,state,ret); The callback should return 'ret', state is for
|
||||
// compatibility with the SSL info_callback.
|
||||
int (*info_callback)(const BIO *bio, int state, int ret);
|
||||
} BIO_CONNECT;
|
||||
|
||||
@@ -113,9 +113,9 @@ static int closesocket(int sock) {
|
||||
}
|
||||
#endif
|
||||
|
||||
/* split_host_and_port sets |*out_host| and |*out_port| to the host and port
|
||||
* parsed from |name|. It returns one on success or zero on error. Even when
|
||||
* successful, |*out_port| may be NULL on return if no port was specified. */
|
||||
// split_host_and_port sets |*out_host| and |*out_port| to the host and port
|
||||
// parsed from |name|. It returns one on success or zero on error. Even when
|
||||
// successful, |*out_port| may be NULL on return if no port was specified.
|
||||
static int split_host_and_port(char **out_host, char **out_port, const char *name) {
|
||||
const char *host, *port = NULL;
|
||||
size_t host_len = 0;
|
||||
@@ -123,24 +123,24 @@ static int split_host_and_port(char **out_host, char **out_port, const char *nam
|
||||
*out_host = NULL;
|
||||
*out_port = NULL;
|
||||
|
||||
if (name[0] == '[') { /* bracketed IPv6 address */
|
||||
if (name[0] == '[') { // bracketed IPv6 address
|
||||
const char *close = strchr(name, ']');
|
||||
if (close == NULL) {
|
||||
return 0;
|
||||
}
|
||||
host = name + 1;
|
||||
host_len = close - host;
|
||||
if (close[1] == ':') { /* [IP]:port */
|
||||
if (close[1] == ':') { // [IP]:port
|
||||
port = close + 2;
|
||||
} else if (close[1] != 0) {
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
const char *colon = strchr(name, ':');
|
||||
if (colon == NULL || strchr(colon + 1, ':') != NULL) { /* IPv6 address */
|
||||
if (colon == NULL || strchr(colon + 1, ':') != NULL) { // IPv6 address
|
||||
host = name;
|
||||
host_len = strlen(name);
|
||||
} else { /* host:port */
|
||||
} else { // host:port
|
||||
host = name;
|
||||
host_len = colon - name;
|
||||
port = colon + 1;
|
||||
@@ -175,9 +175,9 @@ static int conn_state(BIO *bio, BIO_CONNECT *c) {
|
||||
for (;;) {
|
||||
switch (c->state) {
|
||||
case BIO_CONN_S_BEFORE:
|
||||
/* If there's a hostname and a port, assume that both are
|
||||
* exactly what they say. If there is only a hostname, try
|
||||
* (just once) to split it into a hostname and port. */
|
||||
// If there's a hostname and a port, assume that both are
|
||||
// exactly what they say. If there is only a hostname, try
|
||||
// (just once) to split it into a hostname and port.
|
||||
|
||||
if (c->param_hostname == NULL) {
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_R_NO_HOSTNAME_SPECIFIED);
|
||||
@@ -330,7 +330,7 @@ static void conn_close_socket(BIO *bio) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Only do a shutdown if things were established */
|
||||
// Only do a shutdown if things were established
|
||||
if (c->state == BIO_CONN_S_OK) {
|
||||
shutdown(bio->num, 2);
|
||||
}
|
||||
@@ -415,7 +415,7 @@ static long conn_ctrl(BIO *bio, int cmd, long num, void *ptr) {
|
||||
bio->flags = 0;
|
||||
break;
|
||||
case BIO_C_DO_STATE_MACHINE:
|
||||
/* use this one to start the connection */
|
||||
// use this one to start the connection
|
||||
if (data->state != BIO_CONN_S_OK) {
|
||||
ret = (long)conn_state(bio, data);
|
||||
} else {
|
||||
|
||||
+1
-1
@@ -138,7 +138,7 @@ BIO *BIO_new_fd(int fd, int close_flag) {
|
||||
}
|
||||
|
||||
static int fd_new(BIO *bio) {
|
||||
/* num is used to store the file descriptor. */
|
||||
// num is used to store the file descriptor.
|
||||
bio->num = -1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
+13
-14
@@ -55,18 +55,17 @@
|
||||
* [including the GNU Public Licence.] */
|
||||
|
||||
#if defined(__linux) || defined(__sun) || defined(__hpux)
|
||||
/* Following definition aliases fopen to fopen64 on above mentioned
|
||||
* platforms. This makes it possible to open and sequentially access
|
||||
* files larger than 2GB from 32-bit application. It does not allow to
|
||||
* traverse them beyond 2GB with fseek/ftell, but on the other hand *no*
|
||||
* 32-bit platform permits that, not with fseek/ftell. Not to mention
|
||||
* that breaking 2GB limit for seeking would require surgery to *our*
|
||||
* API. But sequential access suffices for practical cases when you
|
||||
* can run into large files, such as fingerprinting, so we can let API
|
||||
* alone. For reference, the list of 32-bit platforms which allow for
|
||||
* sequential access of large files without extra "magic" comprise *BSD,
|
||||
* Darwin, IRIX...
|
||||
*/
|
||||
// Following definition aliases fopen to fopen64 on above mentioned
|
||||
// platforms. This makes it possible to open and sequentially access
|
||||
// files larger than 2GB from 32-bit application. It does not allow to
|
||||
// traverse them beyond 2GB with fseek/ftell, but on the other hand *no*
|
||||
// 32-bit platform permits that, not with fseek/ftell. Not to mention
|
||||
// that breaking 2GB limit for seeking would require surgery to *our*
|
||||
// API. But sequential access suffices for practical cases when you
|
||||
// can run into large files, such as fingerprinting, so we can let API
|
||||
// alone. For reference, the list of 32-bit platforms which allow for
|
||||
// sequential access of large files without extra "magic" comprise *BSD,
|
||||
// Darwin, IRIX...
|
||||
#ifndef _FILE_OFFSET_BITS
|
||||
#define _FILE_OFFSET_BITS 64
|
||||
#endif
|
||||
@@ -157,7 +156,7 @@ static int file_read(BIO *b, char *out, int outl) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* fread reads at most |outl| bytes, so |ret| fits in an int. */
|
||||
// fread reads at most |outl| bytes, so |ret| fits in an int.
|
||||
return (int)ret;
|
||||
}
|
||||
|
||||
@@ -232,7 +231,7 @@ static long file_ctrl(BIO *b, int cmd, long num, void *ptr) {
|
||||
b->init = 1;
|
||||
break;
|
||||
case BIO_C_GET_FILE_PTR:
|
||||
/* the ptr parameter is actually a FILE ** in this case. */
|
||||
// the ptr parameter is actually a FILE ** in this case.
|
||||
if (ptr != NULL) {
|
||||
fpp = (FILE **)ptr;
|
||||
*fpp = (FILE *)b->ptr;
|
||||
|
||||
+15
-16
@@ -62,12 +62,12 @@
|
||||
#include "../internal.h"
|
||||
|
||||
|
||||
/* hexdump_ctx contains the state of a hexdump. */
|
||||
// hexdump_ctx contains the state of a hexdump.
|
||||
struct hexdump_ctx {
|
||||
BIO *bio;
|
||||
char right_chars[18]; /* the contents of the right-hand side, ASCII dump. */
|
||||
unsigned used; /* number of bytes in the current line. */
|
||||
size_t n; /* number of bytes total. */
|
||||
char right_chars[18]; // the contents of the right-hand side, ASCII dump.
|
||||
unsigned used; // number of bytes in the current line.
|
||||
size_t n; // number of bytes total.
|
||||
unsigned indent;
|
||||
};
|
||||
|
||||
@@ -84,21 +84,20 @@ static char to_char(uint8_t b) {
|
||||
return b;
|
||||
}
|
||||
|
||||
/* hexdump_write adds |len| bytes of |data| to the current hex dump described by
|
||||
* |ctx|. */
|
||||
// hexdump_write adds |len| bytes of |data| to the current hex dump described by
|
||||
// |ctx|.
|
||||
static int hexdump_write(struct hexdump_ctx *ctx, const uint8_t *data,
|
||||
size_t len) {
|
||||
char buf[10];
|
||||
unsigned l;
|
||||
|
||||
/* Output lines look like:
|
||||
* 00000010 2e 2f 30 31 32 33 34 35 36 37 38 ... 3c 3d // |./0123456789:;<=|
|
||||
* ^ offset ^ extra space ^ ASCII of line
|
||||
*/
|
||||
// Output lines look like:
|
||||
// 00000010 2e 2f 30 31 32 33 34 35 36 37 38 ... 3c 3d // |./0123456789:;<=|
|
||||
// ^ offset ^ extra space ^ ASCII of line
|
||||
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
if (ctx->used == 0) {
|
||||
/* The beginning of a line. */
|
||||
// The beginning of a line.
|
||||
BIO_indent(ctx->bio, ctx->indent, UINT_MAX);
|
||||
|
||||
hexbyte(&buf[0], ctx->n >> 24);
|
||||
@@ -115,12 +114,12 @@ static int hexdump_write(struct hexdump_ctx *ctx, const uint8_t *data,
|
||||
buf[2] = ' ';
|
||||
l = 3;
|
||||
if (ctx->used == 7) {
|
||||
/* There's an additional space after the 8th byte. */
|
||||
// There's an additional space after the 8th byte.
|
||||
buf[3] = ' ';
|
||||
l = 4;
|
||||
} else if (ctx->used == 15) {
|
||||
/* At the end of the line there's an extra space and the bar for the
|
||||
* right column. */
|
||||
// At the end of the line there's an extra space and the bar for the
|
||||
// right column.
|
||||
buf[3] = ' ';
|
||||
buf[4] = '|';
|
||||
l = 5;
|
||||
@@ -145,9 +144,9 @@ static int hexdump_write(struct hexdump_ctx *ctx, const uint8_t *data,
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* finish flushes any buffered data in |ctx|. */
|
||||
// finish flushes any buffered data in |ctx|.
|
||||
static int finish(struct hexdump_ctx *ctx) {
|
||||
/* See the comments in |hexdump| for the details of this format. */
|
||||
// See the comments in |hexdump| for the details of this format.
|
||||
const unsigned n_bytes = ctx->used;
|
||||
unsigned l;
|
||||
char buf[5];
|
||||
|
||||
+14
-14
@@ -61,7 +61,7 @@
|
||||
|
||||
#if !defined(OPENSSL_WINDOWS)
|
||||
#if defined(OPENSSL_PNACL)
|
||||
/* newlib uses u_short in socket.h without defining it. */
|
||||
// newlib uses u_short in socket.h without defining it.
|
||||
typedef unsigned short u_short;
|
||||
#endif
|
||||
#include <sys/types.h>
|
||||
@@ -78,34 +78,34 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/* BIO_ip_and_port_to_socket_and_addr creates a socket and fills in |*out_addr|
|
||||
* and |*out_addr_length| with the correct values for connecting to |hostname|
|
||||
* on |port_str|. It returns one on success or zero on error. */
|
||||
// BIO_ip_and_port_to_socket_and_addr creates a socket and fills in |*out_addr|
|
||||
// and |*out_addr_length| with the correct values for connecting to |hostname|
|
||||
// on |port_str|. It returns one on success or zero on error.
|
||||
int bio_ip_and_port_to_socket_and_addr(int *out_sock,
|
||||
struct sockaddr_storage *out_addr,
|
||||
socklen_t *out_addr_length,
|
||||
const char *hostname,
|
||||
const char *port_str);
|
||||
|
||||
/* BIO_socket_nbio sets whether |sock| is non-blocking. It returns one on
|
||||
* success and zero otherwise. */
|
||||
// BIO_socket_nbio sets whether |sock| is non-blocking. It returns one on
|
||||
// success and zero otherwise.
|
||||
int bio_socket_nbio(int sock, int on);
|
||||
|
||||
/* BIO_clear_socket_error clears the last system socket error.
|
||||
*
|
||||
* TODO(fork): remove all callers of this. */
|
||||
// BIO_clear_socket_error clears the last system socket error.
|
||||
//
|
||||
// TODO(fork): remove all callers of this.
|
||||
void bio_clear_socket_error(void);
|
||||
|
||||
/* BIO_sock_error returns the last socket error on |sock|. */
|
||||
// BIO_sock_error returns the last socket error on |sock|.
|
||||
int bio_sock_error(int sock);
|
||||
|
||||
/* BIO_fd_should_retry returns non-zero if |return_value| indicates an error
|
||||
* and |errno| indicates that it's non-fatal. */
|
||||
// BIO_fd_should_retry returns non-zero if |return_value| indicates an error
|
||||
// and |errno| indicates that it's non-fatal.
|
||||
int bio_fd_should_retry(int return_value);
|
||||
|
||||
|
||||
#if defined(__cplusplus)
|
||||
} /* extern C */
|
||||
} // extern C
|
||||
#endif
|
||||
|
||||
#endif /* OPENSSL_HEADER_BIO_INTERNAL_H */
|
||||
#endif // OPENSSL_HEADER_BIO_INTERNAL_H
|
||||
|
||||
+44
-44
@@ -63,22 +63,22 @@
|
||||
|
||||
|
||||
struct bio_bio_st {
|
||||
BIO *peer; /* NULL if buf == NULL.
|
||||
* If peer != NULL, then peer->ptr is also a bio_bio_st,
|
||||
* and its "peer" member points back to us.
|
||||
* peer != NULL iff init != 0 in the BIO. */
|
||||
BIO *peer; // NULL if buf == NULL.
|
||||
// If peer != NULL, then peer->ptr is also a bio_bio_st,
|
||||
// and its "peer" member points back to us.
|
||||
// peer != NULL iff init != 0 in the BIO.
|
||||
|
||||
/* This is for what we write (i.e. reading uses peer's struct): */
|
||||
int closed; /* valid iff peer != NULL */
|
||||
size_t len; /* valid iff buf != NULL; 0 if peer == NULL */
|
||||
size_t offset; /* valid iff buf != NULL; 0 if len == 0 */
|
||||
// This is for what we write (i.e. reading uses peer's struct):
|
||||
int closed; // valid iff peer != NULL
|
||||
size_t len; // valid iff buf != NULL; 0 if peer == NULL
|
||||
size_t offset; // valid iff buf != NULL; 0 if len == 0
|
||||
size_t size;
|
||||
uint8_t *buf; /* "size" elements (if != NULL) */
|
||||
uint8_t *buf; // "size" elements (if != NULL)
|
||||
|
||||
size_t request; /* valid iff peer != NULL; 0 if len != 0,
|
||||
* otherwise set by peer to number of bytes
|
||||
* it (unsuccessfully) tried to read,
|
||||
* never more than buffer space (size-len) warrants. */
|
||||
size_t request; // valid iff peer != NULL; 0 if len != 0,
|
||||
// otherwise set by peer to number of bytes
|
||||
// it (unsuccessfully) tried to read,
|
||||
// never more than buffer space (size-len) warrants.
|
||||
};
|
||||
|
||||
static int bio_new(BIO *bio) {
|
||||
@@ -90,7 +90,7 @@ static int bio_new(BIO *bio) {
|
||||
}
|
||||
OPENSSL_memset(b, 0, sizeof(struct bio_bio_st));
|
||||
|
||||
b->size = 17 * 1024; /* enough for one TLS record (just a default) */
|
||||
b->size = 17 * 1024; // enough for one TLS record (just a default)
|
||||
bio->ptr = b;
|
||||
return 1;
|
||||
}
|
||||
@@ -165,7 +165,7 @@ static int bio_read(BIO *bio, char *buf, int size_) {
|
||||
assert(peer_b != NULL);
|
||||
assert(peer_b->buf != NULL);
|
||||
|
||||
peer_b->request = 0; /* will be set in "retry_read" situation */
|
||||
peer_b->request = 0; // will be set in "retry_read" situation
|
||||
|
||||
if (buf == NULL || size == 0) {
|
||||
return 0;
|
||||
@@ -173,30 +173,30 @@ static int bio_read(BIO *bio, char *buf, int size_) {
|
||||
|
||||
if (peer_b->len == 0) {
|
||||
if (peer_b->closed) {
|
||||
return 0; /* writer has closed, and no data is left */
|
||||
return 0; // writer has closed, and no data is left
|
||||
} else {
|
||||
BIO_set_retry_read(bio); /* buffer is empty */
|
||||
BIO_set_retry_read(bio); // buffer is empty
|
||||
if (size <= peer_b->size) {
|
||||
peer_b->request = size;
|
||||
} else {
|
||||
/* don't ask for more than the peer can
|
||||
* deliver in one write */
|
||||
// don't ask for more than the peer can
|
||||
// deliver in one write
|
||||
peer_b->request = peer_b->size;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* we can read */
|
||||
// we can read
|
||||
if (peer_b->len < size) {
|
||||
size = peer_b->len;
|
||||
}
|
||||
|
||||
/* now read "size" bytes */
|
||||
// now read "size" bytes
|
||||
rest = size;
|
||||
|
||||
assert(rest > 0);
|
||||
/* one or two iterations */
|
||||
// one or two iterations
|
||||
do {
|
||||
size_t chunk;
|
||||
|
||||
@@ -204,7 +204,7 @@ static int bio_read(BIO *bio, char *buf, int size_) {
|
||||
if (peer_b->offset + rest <= peer_b->size) {
|
||||
chunk = rest;
|
||||
} else {
|
||||
/* wrap around ring buffer */
|
||||
// wrap around ring buffer
|
||||
chunk = peer_b->size - peer_b->offset;
|
||||
}
|
||||
assert(peer_b->offset + chunk <= peer_b->size);
|
||||
@@ -220,7 +220,7 @@ static int bio_read(BIO *bio, char *buf, int size_) {
|
||||
}
|
||||
buf += chunk;
|
||||
} else {
|
||||
/* buffer now empty, no need to advance "buf" */
|
||||
// buffer now empty, no need to advance "buf"
|
||||
assert(chunk == rest);
|
||||
peer_b->offset = 0;
|
||||
}
|
||||
@@ -248,7 +248,7 @@ static int bio_write(BIO *bio, const char *buf, int num_) {
|
||||
|
||||
b->request = 0;
|
||||
if (b->closed) {
|
||||
/* we already closed */
|
||||
// we already closed
|
||||
OPENSSL_PUT_ERROR(BIO, BIO_R_BROKEN_PIPE);
|
||||
return -1;
|
||||
}
|
||||
@@ -256,20 +256,20 @@ static int bio_write(BIO *bio, const char *buf, int num_) {
|
||||
assert(b->len <= b->size);
|
||||
|
||||
if (b->len == b->size) {
|
||||
BIO_set_retry_write(bio); /* buffer is full */
|
||||
BIO_set_retry_write(bio); // buffer is full
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* we can write */
|
||||
// we can write
|
||||
if (num > b->size - b->len) {
|
||||
num = b->size - b->len;
|
||||
}
|
||||
|
||||
/* now write "num" bytes */
|
||||
// now write "num" bytes
|
||||
rest = num;
|
||||
|
||||
assert(rest > 0);
|
||||
/* one or two iterations */
|
||||
// one or two iterations
|
||||
do {
|
||||
size_t write_offset;
|
||||
size_t chunk;
|
||||
@@ -280,12 +280,12 @@ static int bio_write(BIO *bio, const char *buf, int num_) {
|
||||
if (write_offset >= b->size) {
|
||||
write_offset -= b->size;
|
||||
}
|
||||
/* b->buf[write_offset] is the first byte we can write to. */
|
||||
// b->buf[write_offset] is the first byte we can write to.
|
||||
|
||||
if (write_offset + rest <= b->size) {
|
||||
chunk = rest;
|
||||
} else {
|
||||
/* wrap around ring buffer */
|
||||
// wrap around ring buffer
|
||||
chunk = b->size - write_offset;
|
||||
}
|
||||
|
||||
@@ -363,15 +363,15 @@ static long bio_ctrl(BIO *bio, int cmd, long num, void *ptr) {
|
||||
assert(b != NULL);
|
||||
|
||||
switch (cmd) {
|
||||
/* specific CTRL codes */
|
||||
// specific CTRL codes
|
||||
|
||||
case BIO_C_GET_WRITE_BUF_SIZE:
|
||||
ret = (long)b->size;
|
||||
break;
|
||||
|
||||
case BIO_C_GET_WRITE_GUARANTEE:
|
||||
/* How many bytes can the caller feed to the next write
|
||||
* without having to keep any? */
|
||||
// How many bytes can the caller feed to the next write
|
||||
// without having to keep any?
|
||||
if (b->peer == NULL || b->closed) {
|
||||
ret = 0;
|
||||
} else {
|
||||
@@ -380,28 +380,28 @@ static long bio_ctrl(BIO *bio, int cmd, long num, void *ptr) {
|
||||
break;
|
||||
|
||||
case BIO_C_GET_READ_REQUEST:
|
||||
/* If the peer unsuccessfully tried to read, how many bytes
|
||||
* were requested? (As with BIO_CTRL_PENDING, that number
|
||||
* can usually be treated as boolean.) */
|
||||
// If the peer unsuccessfully tried to read, how many bytes
|
||||
// were requested? (As with BIO_CTRL_PENDING, that number
|
||||
// can usually be treated as boolean.)
|
||||
ret = (long)b->request;
|
||||
break;
|
||||
|
||||
case BIO_C_RESET_READ_REQUEST:
|
||||
/* Reset request. (Can be useful after read attempts
|
||||
* at the other side that are meant to be non-blocking,
|
||||
* e.g. when probing SSL_read to see if any data is
|
||||
* available.) */
|
||||
// Reset request. (Can be useful after read attempts
|
||||
// at the other side that are meant to be non-blocking,
|
||||
// e.g. when probing SSL_read to see if any data is
|
||||
// available.)
|
||||
b->request = 0;
|
||||
ret = 1;
|
||||
break;
|
||||
|
||||
case BIO_C_SHUTDOWN_WR:
|
||||
/* similar to shutdown(..., SHUT_WR) */
|
||||
// similar to shutdown(..., SHUT_WR)
|
||||
b->closed = 1;
|
||||
ret = 1;
|
||||
break;
|
||||
|
||||
/* standard CTRL codes follow */
|
||||
// standard CTRL codes follow
|
||||
|
||||
case BIO_CTRL_GET_CLOSE:
|
||||
ret = bio->shutdown;
|
||||
@@ -453,7 +453,7 @@ static long bio_ctrl(BIO *bio, int cmd, long num, void *ptr) {
|
||||
|
||||
static const BIO_METHOD methods_biop = {
|
||||
BIO_TYPE_BIO, "BIO pair", bio_write, bio_read, NULL /* puts */,
|
||||
NULL /* gets */, bio_ctrl, bio_new, bio_free, NULL /* callback_ctrl */
|
||||
NULL /* gets */, bio_ctrl, bio_new, bio_free, NULL /* callback_ctrl */,
|
||||
};
|
||||
|
||||
static const BIO_METHOD *bio_s_bio(void) { return &methods_biop; }
|
||||
|
||||
+7
-7
@@ -55,7 +55,7 @@
|
||||
* [including the GNU Public Licence.] */
|
||||
|
||||
#if !defined(_POSIX_C_SOURCE)
|
||||
#define _POSIX_C_SOURCE 201410L /* for snprintf, vprintf etc */
|
||||
#define _POSIX_C_SOURCE 201410L // for snprintf, vprintf etc
|
||||
#endif
|
||||
|
||||
#include <openssl/bio.h>
|
||||
@@ -77,13 +77,13 @@ int BIO_printf(BIO *bio, const char *format, ...) {
|
||||
va_end(args);
|
||||
|
||||
#if defined(OPENSSL_WINDOWS)
|
||||
/* On Windows, vsnprintf returns -1 rather than the requested length on
|
||||
* truncation */
|
||||
// On Windows, vsnprintf returns -1 rather than the requested length on
|
||||
// truncation
|
||||
if (out_len < 0) {
|
||||
va_start(args, format);
|
||||
out_len = _vscprintf(format, args);
|
||||
va_end(args);
|
||||
assert(out_len >= sizeof(buf));
|
||||
assert(out_len >= (int)sizeof(buf));
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -93,9 +93,9 @@ int BIO_printf(BIO *bio, const char *format, ...) {
|
||||
|
||||
if ((size_t) out_len >= sizeof(buf)) {
|
||||
const int requested_len = out_len;
|
||||
/* The output was truncated. Note that vsnprintf's return value
|
||||
* does not include a trailing NUL, but the buffer must be sized
|
||||
* for it. */
|
||||
// The output was truncated. Note that vsnprintf's return value
|
||||
// does not include a trailing NUL, but the buffer must be sized
|
||||
// for it.
|
||||
out = OPENSSL_malloc(requested_len + 1);
|
||||
out_malloced = 1;
|
||||
if (out == NULL) {
|
||||
|
||||
@@ -1,87 +0,0 @@
|
||||
include_directories(../../include)
|
||||
|
||||
if (${ARCH} STREQUAL "x86_64")
|
||||
set(
|
||||
BN_ARCH_SOURCES
|
||||
|
||||
x86_64-mont.${ASM_EXT}
|
||||
x86_64-mont5.${ASM_EXT}
|
||||
rsaz-avx2.${ASM_EXT}
|
||||
|
||||
rsaz_exp.c
|
||||
)
|
||||
endif()
|
||||
|
||||
if (${ARCH} STREQUAL "x86")
|
||||
set(
|
||||
BN_ARCH_SOURCES
|
||||
|
||||
bn-586.${ASM_EXT}
|
||||
co-586.${ASM_EXT}
|
||||
x86-mont.${ASM_EXT}
|
||||
)
|
||||
endif()
|
||||
|
||||
if (${ARCH} STREQUAL "arm")
|
||||
set(
|
||||
BN_ARCH_SOURCES
|
||||
|
||||
armv4-mont.${ASM_EXT}
|
||||
)
|
||||
endif()
|
||||
|
||||
if (${ARCH} STREQUAL "aarch64")
|
||||
set(
|
||||
BN_ARCH_SOURCES
|
||||
|
||||
armv8-mont.${ASM_EXT}
|
||||
)
|
||||
endif()
|
||||
|
||||
add_library(
|
||||
bn
|
||||
|
||||
OBJECT
|
||||
|
||||
add.c
|
||||
asm/x86_64-gcc.c
|
||||
bn.c
|
||||
bn_asn1.c
|
||||
cmp.c
|
||||
convert.c
|
||||
ctx.c
|
||||
div.c
|
||||
exponentiation.c
|
||||
generic.c
|
||||
gcd.c
|
||||
kronecker.c
|
||||
montgomery.c
|
||||
montgomery_inv.c
|
||||
mul.c
|
||||
prime.c
|
||||
random.c
|
||||
shift.c
|
||||
sqrt.c
|
||||
|
||||
${BN_ARCH_SOURCES}
|
||||
)
|
||||
|
||||
perlasm(x86_64-mont.${ASM_EXT} asm/x86_64-mont.pl)
|
||||
perlasm(x86_64-mont5.${ASM_EXT} asm/x86_64-mont5.pl)
|
||||
perlasm(rsaz-avx2.${ASM_EXT} asm/rsaz-avx2.pl)
|
||||
perlasm(bn-586.${ASM_EXT} asm/bn-586.pl)
|
||||
perlasm(co-586.${ASM_EXT} asm/co-586.pl)
|
||||
perlasm(x86-mont.${ASM_EXT} asm/x86-mont.pl)
|
||||
perlasm(armv4-mont.${ASM_EXT} asm/armv4-mont.pl)
|
||||
perlasm(armv8-mont.${ASM_EXT} asm/armv8-mont.pl)
|
||||
|
||||
add_executable(
|
||||
bn_test
|
||||
|
||||
bn_test.cc
|
||||
|
||||
$<TARGET_OBJECTS:test_support>
|
||||
)
|
||||
|
||||
target_link_libraries(bn_test crypto)
|
||||
add_dependencies(all_tests bn_test)
|
||||
@@ -1,693 +0,0 @@
|
||||
#!/usr/bin/env perl
|
||||
|
||||
# ====================================================================
|
||||
# Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
|
||||
# project. The module is, however, dual licensed under OpenSSL and
|
||||
# CRYPTOGAMS licenses depending on where you obtain it. For further
|
||||
# details see http://www.openssl.org/~appro/cryptogams/.
|
||||
# ====================================================================
|
||||
|
||||
# January 2007.
|
||||
|
||||
# Montgomery multiplication for ARMv4.
|
||||
#
|
||||
# Performance improvement naturally varies among CPU implementations
|
||||
# and compilers. The code was observed to provide +65-35% improvement
|
||||
# [depending on key length, less for longer keys] on ARM920T, and
|
||||
# +115-80% on Intel IXP425. This is compared to pre-bn_mul_mont code
|
||||
# base and compiler generated code with in-lined umull and even umlal
|
||||
# instructions. The latter means that this code didn't really have an
|
||||
# "advantage" of utilizing some "secret" instruction.
|
||||
#
|
||||
# The code is interoperable with Thumb ISA and is rather compact, less
|
||||
# than 1/2KB. Windows CE port would be trivial, as it's exclusively
|
||||
# about decorations, ABI and instruction syntax are identical.
|
||||
|
||||
# November 2013
|
||||
#
|
||||
# Add NEON code path, which handles lengths divisible by 8. RSA/DSA
|
||||
# performance improvement on Cortex-A8 is ~45-100% depending on key
|
||||
# length, more for longer keys. On Cortex-A15 the span is ~10-105%.
|
||||
# On Snapdragon S4 improvement was measured to vary from ~70% to
|
||||
# incredible ~380%, yes, 4.8x faster, for RSA4096 sign. But this is
|
||||
# rather because original integer-only code seems to perform
|
||||
# suboptimally on S4. Situation on Cortex-A9 is unfortunately
|
||||
# different. It's being looked into, but the trouble is that
|
||||
# performance for vectors longer than 256 bits is actually couple
|
||||
# of percent worse than for integer-only code. The code is chosen
|
||||
# for execution on all NEON-capable processors, because gain on
|
||||
# others outweighs the marginal loss on Cortex-A9.
|
||||
|
||||
$flavour = shift;
|
||||
if ($flavour=~/\w[\w\-]*\.\w+$/) { $output=$flavour; undef $flavour; }
|
||||
else { while (($output=shift) && ($output!~/\w[\w\-]*\.\w+$/)) {} }
|
||||
|
||||
if ($flavour && $flavour ne "void") {
|
||||
$0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1;
|
||||
( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or
|
||||
( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or
|
||||
die "can't locate arm-xlate.pl";
|
||||
|
||||
open STDOUT,"| \"$^X\" $xlate $flavour $output";
|
||||
} else {
|
||||
open STDOUT,">$output";
|
||||
}
|
||||
|
||||
$num="r0"; # starts as num argument, but holds &tp[num-1]
|
||||
$ap="r1";
|
||||
$bp="r2"; $bi="r2"; $rp="r2";
|
||||
$np="r3";
|
||||
$tp="r4";
|
||||
$aj="r5";
|
||||
$nj="r6";
|
||||
$tj="r7";
|
||||
$n0="r8";
|
||||
########### # r9 is reserved by ELF as platform specific, e.g. TLS pointer
|
||||
$alo="r10"; # sl, gcc uses it to keep @GOT
|
||||
$ahi="r11"; # fp
|
||||
$nlo="r12"; # ip
|
||||
########### # r13 is stack pointer
|
||||
$nhi="r14"; # lr
|
||||
########### # r15 is program counter
|
||||
|
||||
#### argument block layout relative to &tp[num-1], a.k.a. $num
|
||||
$_rp="$num,#12*4";
|
||||
# ap permanently resides in r1
|
||||
$_bp="$num,#13*4";
|
||||
# np permanently resides in r3
|
||||
$_n0="$num,#14*4";
|
||||
$_num="$num,#15*4"; $_bpend=$_num;
|
||||
|
||||
$code=<<___;
|
||||
#include <openssl/arm_arch.h>
|
||||
|
||||
.text
|
||||
.code 32
|
||||
|
||||
#if __ARM_MAX_ARCH__>=7
|
||||
.align 5
|
||||
.LOPENSSL_armcap:
|
||||
.word OPENSSL_armcap_P-.Lbn_mul_mont
|
||||
#endif
|
||||
|
||||
.global bn_mul_mont
|
||||
.type bn_mul_mont,%function
|
||||
|
||||
.align 5
|
||||
bn_mul_mont:
|
||||
.Lbn_mul_mont:
|
||||
ldr ip,[sp,#4] @ load num
|
||||
stmdb sp!,{r0,r2} @ sp points at argument block
|
||||
#if __ARM_MAX_ARCH__>=7
|
||||
tst ip,#7
|
||||
bne .Lialu
|
||||
adr r0,bn_mul_mont
|
||||
ldr r2,.LOPENSSL_armcap
|
||||
ldr r0,[r0,r2]
|
||||
#ifdef __APPLE__
|
||||
ldr r0,[r0]
|
||||
#endif
|
||||
tst r0,#ARMV7_NEON @ NEON available?
|
||||
ldmia sp, {r0,r2}
|
||||
beq .Lialu
|
||||
add sp,sp,#8
|
||||
b bn_mul8x_mont_neon
|
||||
.align 4
|
||||
.Lialu:
|
||||
#endif
|
||||
cmp ip,#2
|
||||
mov $num,ip @ load num
|
||||
movlt r0,#0
|
||||
addlt sp,sp,#2*4
|
||||
blt .Labrt
|
||||
|
||||
stmdb sp!,{r4-r12,lr} @ save 10 registers
|
||||
|
||||
mov $num,$num,lsl#2 @ rescale $num for byte count
|
||||
sub sp,sp,$num @ alloca(4*num)
|
||||
sub sp,sp,#4 @ +extra dword
|
||||
sub $num,$num,#4 @ "num=num-1"
|
||||
add $tp,$bp,$num @ &bp[num-1]
|
||||
|
||||
add $num,sp,$num @ $num to point at &tp[num-1]
|
||||
ldr $n0,[$_n0] @ &n0
|
||||
ldr $bi,[$bp] @ bp[0]
|
||||
ldr $aj,[$ap],#4 @ ap[0],ap++
|
||||
ldr $nj,[$np],#4 @ np[0],np++
|
||||
ldr $n0,[$n0] @ *n0
|
||||
str $tp,[$_bpend] @ save &bp[num]
|
||||
|
||||
umull $alo,$ahi,$aj,$bi @ ap[0]*bp[0]
|
||||
str $n0,[$_n0] @ save n0 value
|
||||
mul $n0,$alo,$n0 @ "tp[0]"*n0
|
||||
mov $nlo,#0
|
||||
umlal $alo,$nlo,$nj,$n0 @ np[0]*n0+"t[0]"
|
||||
mov $tp,sp
|
||||
|
||||
.L1st:
|
||||
ldr $aj,[$ap],#4 @ ap[j],ap++
|
||||
mov $alo,$ahi
|
||||
ldr $nj,[$np],#4 @ np[j],np++
|
||||
mov $ahi,#0
|
||||
umlal $alo,$ahi,$aj,$bi @ ap[j]*bp[0]
|
||||
mov $nhi,#0
|
||||
umlal $nlo,$nhi,$nj,$n0 @ np[j]*n0
|
||||
adds $nlo,$nlo,$alo
|
||||
str $nlo,[$tp],#4 @ tp[j-1]=,tp++
|
||||
adc $nlo,$nhi,#0
|
||||
cmp $tp,$num
|
||||
bne .L1st
|
||||
|
||||
adds $nlo,$nlo,$ahi
|
||||
ldr $tp,[$_bp] @ restore bp
|
||||
mov $nhi,#0
|
||||
ldr $n0,[$_n0] @ restore n0
|
||||
adc $nhi,$nhi,#0
|
||||
str $nlo,[$num] @ tp[num-1]=
|
||||
str $nhi,[$num,#4] @ tp[num]=
|
||||
|
||||
.Louter:
|
||||
sub $tj,$num,sp @ "original" $num-1 value
|
||||
sub $ap,$ap,$tj @ "rewind" ap to &ap[1]
|
||||
ldr $bi,[$tp,#4]! @ *(++bp)
|
||||
sub $np,$np,$tj @ "rewind" np to &np[1]
|
||||
ldr $aj,[$ap,#-4] @ ap[0]
|
||||
ldr $alo,[sp] @ tp[0]
|
||||
ldr $nj,[$np,#-4] @ np[0]
|
||||
ldr $tj,[sp,#4] @ tp[1]
|
||||
|
||||
mov $ahi,#0
|
||||
umlal $alo,$ahi,$aj,$bi @ ap[0]*bp[i]+tp[0]
|
||||
str $tp,[$_bp] @ save bp
|
||||
mul $n0,$alo,$n0
|
||||
mov $nlo,#0
|
||||
umlal $alo,$nlo,$nj,$n0 @ np[0]*n0+"tp[0]"
|
||||
mov $tp,sp
|
||||
|
||||
.Linner:
|
||||
ldr $aj,[$ap],#4 @ ap[j],ap++
|
||||
adds $alo,$ahi,$tj @ +=tp[j]
|
||||
ldr $nj,[$np],#4 @ np[j],np++
|
||||
mov $ahi,#0
|
||||
umlal $alo,$ahi,$aj,$bi @ ap[j]*bp[i]
|
||||
mov $nhi,#0
|
||||
umlal $nlo,$nhi,$nj,$n0 @ np[j]*n0
|
||||
adc $ahi,$ahi,#0
|
||||
ldr $tj,[$tp,#8] @ tp[j+1]
|
||||
adds $nlo,$nlo,$alo
|
||||
str $nlo,[$tp],#4 @ tp[j-1]=,tp++
|
||||
adc $nlo,$nhi,#0
|
||||
cmp $tp,$num
|
||||
bne .Linner
|
||||
|
||||
adds $nlo,$nlo,$ahi
|
||||
mov $nhi,#0
|
||||
ldr $tp,[$_bp] @ restore bp
|
||||
adc $nhi,$nhi,#0
|
||||
ldr $n0,[$_n0] @ restore n0
|
||||
adds $nlo,$nlo,$tj
|
||||
ldr $tj,[$_bpend] @ restore &bp[num]
|
||||
adc $nhi,$nhi,#0
|
||||
str $nlo,[$num] @ tp[num-1]=
|
||||
str $nhi,[$num,#4] @ tp[num]=
|
||||
|
||||
cmp $tp,$tj
|
||||
bne .Louter
|
||||
|
||||
ldr $rp,[$_rp] @ pull rp
|
||||
add $num,$num,#4 @ $num to point at &tp[num]
|
||||
sub $aj,$num,sp @ "original" num value
|
||||
mov $tp,sp @ "rewind" $tp
|
||||
mov $ap,$tp @ "borrow" $ap
|
||||
sub $np,$np,$aj @ "rewind" $np to &np[0]
|
||||
|
||||
subs $tj,$tj,$tj @ "clear" carry flag
|
||||
.Lsub: ldr $tj,[$tp],#4
|
||||
ldr $nj,[$np],#4
|
||||
sbcs $tj,$tj,$nj @ tp[j]-np[j]
|
||||
str $tj,[$rp],#4 @ rp[j]=
|
||||
teq $tp,$num @ preserve carry
|
||||
bne .Lsub
|
||||
sbcs $nhi,$nhi,#0 @ upmost carry
|
||||
mov $tp,sp @ "rewind" $tp
|
||||
sub $rp,$rp,$aj @ "rewind" $rp
|
||||
|
||||
and $ap,$tp,$nhi
|
||||
bic $np,$rp,$nhi
|
||||
orr $ap,$ap,$np @ ap=borrow?tp:rp
|
||||
|
||||
.Lcopy: ldr $tj,[$ap],#4 @ copy or in-place refresh
|
||||
str sp,[$tp],#4 @ zap tp
|
||||
str $tj,[$rp],#4
|
||||
cmp $tp,$num
|
||||
bne .Lcopy
|
||||
|
||||
add sp,$num,#4 @ skip over tp[num+1]
|
||||
ldmia sp!,{r4-r12,lr} @ restore registers
|
||||
add sp,sp,#2*4 @ skip over {r0,r2}
|
||||
mov r0,#1
|
||||
.Labrt:
|
||||
#if __ARM_ARCH__>=5
|
||||
ret @ bx lr
|
||||
#else
|
||||
tst lr,#1
|
||||
moveq pc,lr @ be binary compatible with V4, yet
|
||||
bx lr @ interoperable with Thumb ISA:-)
|
||||
#endif
|
||||
.size bn_mul_mont,.-bn_mul_mont
|
||||
___
|
||||
{
|
||||
sub Dlo() { shift=~m|q([1]?[0-9])|?"d".($1*2):""; }
|
||||
sub Dhi() { shift=~m|q([1]?[0-9])|?"d".($1*2+1):""; }
|
||||
|
||||
my ($A0,$A1,$A2,$A3)=map("d$_",(0..3));
|
||||
my ($N0,$N1,$N2,$N3)=map("d$_",(4..7));
|
||||
my ($Z,$Temp)=("q4","q5");
|
||||
my ($A0xB,$A1xB,$A2xB,$A3xB,$A4xB,$A5xB,$A6xB,$A7xB)=map("q$_",(6..13));
|
||||
my ($Bi,$Ni,$M0)=map("d$_",(28..31));
|
||||
my $zero=&Dlo($Z);
|
||||
my $temp=&Dlo($Temp);
|
||||
|
||||
my ($rptr,$aptr,$bptr,$nptr,$n0,$num)=map("r$_",(0..5));
|
||||
my ($tinptr,$toutptr,$inner,$outer)=map("r$_",(6..9));
|
||||
|
||||
$code.=<<___;
|
||||
#if __ARM_MAX_ARCH__>=7
|
||||
.arch armv7-a
|
||||
.fpu neon
|
||||
|
||||
.type bn_mul8x_mont_neon,%function
|
||||
.align 5
|
||||
bn_mul8x_mont_neon:
|
||||
mov ip,sp
|
||||
stmdb sp!,{r4-r11}
|
||||
vstmdb sp!,{d8-d15} @ ABI specification says so
|
||||
ldmia ip,{r4-r5} @ load rest of parameter block
|
||||
|
||||
sub $toutptr,sp,#16
|
||||
vld1.32 {${Bi}[0]}, [$bptr,:32]!
|
||||
sub $toutptr,$toutptr,$num,lsl#4
|
||||
vld1.32 {$A0-$A3}, [$aptr]! @ can't specify :32 :-(
|
||||
and $toutptr,$toutptr,#-64
|
||||
vld1.32 {${M0}[0]}, [$n0,:32]
|
||||
mov sp,$toutptr @ alloca
|
||||
veor $zero,$zero,$zero
|
||||
subs $inner,$num,#8
|
||||
vzip.16 $Bi,$zero
|
||||
|
||||
vmull.u32 $A0xB,$Bi,${A0}[0]
|
||||
vmull.u32 $A1xB,$Bi,${A0}[1]
|
||||
vmull.u32 $A2xB,$Bi,${A1}[0]
|
||||
vshl.i64 $temp,`&Dhi("$A0xB")`,#16
|
||||
vmull.u32 $A3xB,$Bi,${A1}[1]
|
||||
|
||||
vadd.u64 $temp,$temp,`&Dlo("$A0xB")`
|
||||
veor $zero,$zero,$zero
|
||||
vmul.u32 $Ni,$temp,$M0
|
||||
|
||||
vmull.u32 $A4xB,$Bi,${A2}[0]
|
||||
vld1.32 {$N0-$N3}, [$nptr]!
|
||||
vmull.u32 $A5xB,$Bi,${A2}[1]
|
||||
vmull.u32 $A6xB,$Bi,${A3}[0]
|
||||
vzip.16 $Ni,$zero
|
||||
vmull.u32 $A7xB,$Bi,${A3}[1]
|
||||
|
||||
bne .LNEON_1st
|
||||
|
||||
@ special case for num=8, everything is in register bank...
|
||||
|
||||
vmlal.u32 $A0xB,$Ni,${N0}[0]
|
||||
sub $outer,$num,#1
|
||||
vmlal.u32 $A1xB,$Ni,${N0}[1]
|
||||
vmlal.u32 $A2xB,$Ni,${N1}[0]
|
||||
vmlal.u32 $A3xB,$Ni,${N1}[1]
|
||||
|
||||
vmlal.u32 $A4xB,$Ni,${N2}[0]
|
||||
vmov $Temp,$A0xB
|
||||
vmlal.u32 $A5xB,$Ni,${N2}[1]
|
||||
vmov $A0xB,$A1xB
|
||||
vmlal.u32 $A6xB,$Ni,${N3}[0]
|
||||
vmov $A1xB,$A2xB
|
||||
vmlal.u32 $A7xB,$Ni,${N3}[1]
|
||||
vmov $A2xB,$A3xB
|
||||
vmov $A3xB,$A4xB
|
||||
vshr.u64 $temp,$temp,#16
|
||||
vmov $A4xB,$A5xB
|
||||
vmov $A5xB,$A6xB
|
||||
vadd.u64 $temp,$temp,`&Dhi("$Temp")`
|
||||
vmov $A6xB,$A7xB
|
||||
veor $A7xB,$A7xB
|
||||
vshr.u64 $temp,$temp,#16
|
||||
|
||||
b .LNEON_outer8
|
||||
|
||||
.align 4
|
||||
.LNEON_outer8:
|
||||
vld1.32 {${Bi}[0]}, [$bptr,:32]!
|
||||
veor $zero,$zero,$zero
|
||||
vzip.16 $Bi,$zero
|
||||
vadd.u64 `&Dlo("$A0xB")`,`&Dlo("$A0xB")`,$temp
|
||||
|
||||
vmlal.u32 $A0xB,$Bi,${A0}[0]
|
||||
vmlal.u32 $A1xB,$Bi,${A0}[1]
|
||||
vmlal.u32 $A2xB,$Bi,${A1}[0]
|
||||
vshl.i64 $temp,`&Dhi("$A0xB")`,#16
|
||||
vmlal.u32 $A3xB,$Bi,${A1}[1]
|
||||
|
||||
vadd.u64 $temp,$temp,`&Dlo("$A0xB")`
|
||||
veor $zero,$zero,$zero
|
||||
subs $outer,$outer,#1
|
||||
vmul.u32 $Ni,$temp,$M0
|
||||
|
||||
vmlal.u32 $A4xB,$Bi,${A2}[0]
|
||||
vmlal.u32 $A5xB,$Bi,${A2}[1]
|
||||
vmlal.u32 $A6xB,$Bi,${A3}[0]
|
||||
vzip.16 $Ni,$zero
|
||||
vmlal.u32 $A7xB,$Bi,${A3}[1]
|
||||
|
||||
vmlal.u32 $A0xB,$Ni,${N0}[0]
|
||||
vmlal.u32 $A1xB,$Ni,${N0}[1]
|
||||
vmlal.u32 $A2xB,$Ni,${N1}[0]
|
||||
vmlal.u32 $A3xB,$Ni,${N1}[1]
|
||||
|
||||
vmlal.u32 $A4xB,$Ni,${N2}[0]
|
||||
vmov $Temp,$A0xB
|
||||
vmlal.u32 $A5xB,$Ni,${N2}[1]
|
||||
vmov $A0xB,$A1xB
|
||||
vmlal.u32 $A6xB,$Ni,${N3}[0]
|
||||
vmov $A1xB,$A2xB
|
||||
vmlal.u32 $A7xB,$Ni,${N3}[1]
|
||||
vmov $A2xB,$A3xB
|
||||
vmov $A3xB,$A4xB
|
||||
vshr.u64 $temp,$temp,#16
|
||||
vmov $A4xB,$A5xB
|
||||
vmov $A5xB,$A6xB
|
||||
vadd.u64 $temp,$temp,`&Dhi("$Temp")`
|
||||
vmov $A6xB,$A7xB
|
||||
veor $A7xB,$A7xB
|
||||
vshr.u64 $temp,$temp,#16
|
||||
|
||||
bne .LNEON_outer8
|
||||
|
||||
vadd.u64 `&Dlo("$A0xB")`,`&Dlo("$A0xB")`,$temp
|
||||
mov $toutptr,sp
|
||||
vshr.u64 $temp,`&Dlo("$A0xB")`,#16
|
||||
mov $inner,$num
|
||||
vadd.u64 `&Dhi("$A0xB")`,`&Dhi("$A0xB")`,$temp
|
||||
add $tinptr,sp,#16
|
||||
vshr.u64 $temp,`&Dhi("$A0xB")`,#16
|
||||
vzip.16 `&Dlo("$A0xB")`,`&Dhi("$A0xB")`
|
||||
|
||||
b .LNEON_tail2
|
||||
|
||||
.align 4
|
||||
.LNEON_1st:
|
||||
vmlal.u32 $A0xB,$Ni,${N0}[0]
|
||||
vld1.32 {$A0-$A3}, [$aptr]!
|
||||
vmlal.u32 $A1xB,$Ni,${N0}[1]
|
||||
subs $inner,$inner,#8
|
||||
vmlal.u32 $A2xB,$Ni,${N1}[0]
|
||||
vmlal.u32 $A3xB,$Ni,${N1}[1]
|
||||
|
||||
vmlal.u32 $A4xB,$Ni,${N2}[0]
|
||||
vld1.32 {$N0-$N1}, [$nptr]!
|
||||
vmlal.u32 $A5xB,$Ni,${N2}[1]
|
||||
vst1.64 {$A0xB-$A1xB}, [$toutptr,:256]!
|
||||
vmlal.u32 $A6xB,$Ni,${N3}[0]
|
||||
vmlal.u32 $A7xB,$Ni,${N3}[1]
|
||||
vst1.64 {$A2xB-$A3xB}, [$toutptr,:256]!
|
||||
|
||||
vmull.u32 $A0xB,$Bi,${A0}[0]
|
||||
vld1.32 {$N2-$N3}, [$nptr]!
|
||||
vmull.u32 $A1xB,$Bi,${A0}[1]
|
||||
vst1.64 {$A4xB-$A5xB}, [$toutptr,:256]!
|
||||
vmull.u32 $A2xB,$Bi,${A1}[0]
|
||||
vmull.u32 $A3xB,$Bi,${A1}[1]
|
||||
vst1.64 {$A6xB-$A7xB}, [$toutptr,:256]!
|
||||
|
||||
vmull.u32 $A4xB,$Bi,${A2}[0]
|
||||
vmull.u32 $A5xB,$Bi,${A2}[1]
|
||||
vmull.u32 $A6xB,$Bi,${A3}[0]
|
||||
vmull.u32 $A7xB,$Bi,${A3}[1]
|
||||
|
||||
bne .LNEON_1st
|
||||
|
||||
vmlal.u32 $A0xB,$Ni,${N0}[0]
|
||||
add $tinptr,sp,#16
|
||||
vmlal.u32 $A1xB,$Ni,${N0}[1]
|
||||
sub $aptr,$aptr,$num,lsl#2 @ rewind $aptr
|
||||
vmlal.u32 $A2xB,$Ni,${N1}[0]
|
||||
vld1.64 {$Temp}, [sp,:128]
|
||||
vmlal.u32 $A3xB,$Ni,${N1}[1]
|
||||
sub $outer,$num,#1
|
||||
|
||||
vmlal.u32 $A4xB,$Ni,${N2}[0]
|
||||
vst1.64 {$A0xB-$A1xB}, [$toutptr,:256]!
|
||||
vmlal.u32 $A5xB,$Ni,${N2}[1]
|
||||
vshr.u64 $temp,$temp,#16
|
||||
vld1.64 {$A0xB}, [$tinptr, :128]!
|
||||
vmlal.u32 $A6xB,$Ni,${N3}[0]
|
||||
vst1.64 {$A2xB-$A3xB}, [$toutptr,:256]!
|
||||
vmlal.u32 $A7xB,$Ni,${N3}[1]
|
||||
|
||||
vst1.64 {$A4xB-$A5xB}, [$toutptr,:256]!
|
||||
vadd.u64 $temp,$temp,`&Dhi("$Temp")`
|
||||
veor $Z,$Z,$Z
|
||||
vst1.64 {$A6xB-$A7xB}, [$toutptr,:256]!
|
||||
vld1.64 {$A1xB-$A2xB}, [$tinptr, :256]!
|
||||
vst1.64 {$Z}, [$toutptr,:128]
|
||||
vshr.u64 $temp,$temp,#16
|
||||
|
||||
b .LNEON_outer
|
||||
|
||||
.align 4
|
||||
.LNEON_outer:
|
||||
vld1.32 {${Bi}[0]}, [$bptr,:32]!
|
||||
sub $nptr,$nptr,$num,lsl#2 @ rewind $nptr
|
||||
vld1.32 {$A0-$A3}, [$aptr]!
|
||||
veor $zero,$zero,$zero
|
||||
mov $toutptr,sp
|
||||
vzip.16 $Bi,$zero
|
||||
sub $inner,$num,#8
|
||||
vadd.u64 `&Dlo("$A0xB")`,`&Dlo("$A0xB")`,$temp
|
||||
|
||||
vmlal.u32 $A0xB,$Bi,${A0}[0]
|
||||
vld1.64 {$A3xB-$A4xB},[$tinptr,:256]!
|
||||
vmlal.u32 $A1xB,$Bi,${A0}[1]
|
||||
vmlal.u32 $A2xB,$Bi,${A1}[0]
|
||||
vld1.64 {$A5xB-$A6xB},[$tinptr,:256]!
|
||||
vmlal.u32 $A3xB,$Bi,${A1}[1]
|
||||
|
||||
vshl.i64 $temp,`&Dhi("$A0xB")`,#16
|
||||
veor $zero,$zero,$zero
|
||||
vadd.u64 $temp,$temp,`&Dlo("$A0xB")`
|
||||
vld1.64 {$A7xB},[$tinptr,:128]!
|
||||
vmul.u32 $Ni,$temp,$M0
|
||||
|
||||
vmlal.u32 $A4xB,$Bi,${A2}[0]
|
||||
vld1.32 {$N0-$N3}, [$nptr]!
|
||||
vmlal.u32 $A5xB,$Bi,${A2}[1]
|
||||
vmlal.u32 $A6xB,$Bi,${A3}[0]
|
||||
vzip.16 $Ni,$zero
|
||||
vmlal.u32 $A7xB,$Bi,${A3}[1]
|
||||
|
||||
.LNEON_inner:
|
||||
vmlal.u32 $A0xB,$Ni,${N0}[0]
|
||||
vld1.32 {$A0-$A3}, [$aptr]!
|
||||
vmlal.u32 $A1xB,$Ni,${N0}[1]
|
||||
subs $inner,$inner,#8
|
||||
vmlal.u32 $A2xB,$Ni,${N1}[0]
|
||||
vmlal.u32 $A3xB,$Ni,${N1}[1]
|
||||
vst1.64 {$A0xB-$A1xB}, [$toutptr,:256]!
|
||||
|
||||
vmlal.u32 $A4xB,$Ni,${N2}[0]
|
||||
vld1.64 {$A0xB}, [$tinptr, :128]!
|
||||
vmlal.u32 $A5xB,$Ni,${N2}[1]
|
||||
vst1.64 {$A2xB-$A3xB}, [$toutptr,:256]!
|
||||
vmlal.u32 $A6xB,$Ni,${N3}[0]
|
||||
vld1.64 {$A1xB-$A2xB}, [$tinptr, :256]!
|
||||
vmlal.u32 $A7xB,$Ni,${N3}[1]
|
||||
vst1.64 {$A4xB-$A5xB}, [$toutptr,:256]!
|
||||
|
||||
vmlal.u32 $A0xB,$Bi,${A0}[0]
|
||||
vld1.64 {$A3xB-$A4xB}, [$tinptr, :256]!
|
||||
vmlal.u32 $A1xB,$Bi,${A0}[1]
|
||||
vst1.64 {$A6xB-$A7xB}, [$toutptr,:256]!
|
||||
vmlal.u32 $A2xB,$Bi,${A1}[0]
|
||||
vld1.64 {$A5xB-$A6xB}, [$tinptr, :256]!
|
||||
vmlal.u32 $A3xB,$Bi,${A1}[1]
|
||||
vld1.32 {$N0-$N3}, [$nptr]!
|
||||
|
||||
vmlal.u32 $A4xB,$Bi,${A2}[0]
|
||||
vld1.64 {$A7xB}, [$tinptr, :128]!
|
||||
vmlal.u32 $A5xB,$Bi,${A2}[1]
|
||||
vmlal.u32 $A6xB,$Bi,${A3}[0]
|
||||
vmlal.u32 $A7xB,$Bi,${A3}[1]
|
||||
|
||||
bne .LNEON_inner
|
||||
|
||||
vmlal.u32 $A0xB,$Ni,${N0}[0]
|
||||
add $tinptr,sp,#16
|
||||
vmlal.u32 $A1xB,$Ni,${N0}[1]
|
||||
sub $aptr,$aptr,$num,lsl#2 @ rewind $aptr
|
||||
vmlal.u32 $A2xB,$Ni,${N1}[0]
|
||||
vld1.64 {$Temp}, [sp,:128]
|
||||
vmlal.u32 $A3xB,$Ni,${N1}[1]
|
||||
subs $outer,$outer,#1
|
||||
|
||||
vmlal.u32 $A4xB,$Ni,${N2}[0]
|
||||
vst1.64 {$A0xB-$A1xB}, [$toutptr,:256]!
|
||||
vmlal.u32 $A5xB,$Ni,${N2}[1]
|
||||
vld1.64 {$A0xB}, [$tinptr, :128]!
|
||||
vshr.u64 $temp,$temp,#16
|
||||
vst1.64 {$A2xB-$A3xB}, [$toutptr,:256]!
|
||||
vmlal.u32 $A6xB,$Ni,${N3}[0]
|
||||
vld1.64 {$A1xB-$A2xB}, [$tinptr, :256]!
|
||||
vmlal.u32 $A7xB,$Ni,${N3}[1]
|
||||
|
||||
vst1.64 {$A4xB-$A5xB}, [$toutptr,:256]!
|
||||
vadd.u64 $temp,$temp,`&Dhi("$Temp")`
|
||||
vst1.64 {$A6xB-$A7xB}, [$toutptr,:256]!
|
||||
vshr.u64 $temp,$temp,#16
|
||||
|
||||
bne .LNEON_outer
|
||||
|
||||
mov $toutptr,sp
|
||||
mov $inner,$num
|
||||
|
||||
.LNEON_tail:
|
||||
vadd.u64 `&Dlo("$A0xB")`,`&Dlo("$A0xB")`,$temp
|
||||
vld1.64 {$A3xB-$A4xB}, [$tinptr, :256]!
|
||||
vshr.u64 $temp,`&Dlo("$A0xB")`,#16
|
||||
vadd.u64 `&Dhi("$A0xB")`,`&Dhi("$A0xB")`,$temp
|
||||
vld1.64 {$A5xB-$A6xB}, [$tinptr, :256]!
|
||||
vshr.u64 $temp,`&Dhi("$A0xB")`,#16
|
||||
vld1.64 {$A7xB}, [$tinptr, :128]!
|
||||
vzip.16 `&Dlo("$A0xB")`,`&Dhi("$A0xB")`
|
||||
|
||||
.LNEON_tail2:
|
||||
vadd.u64 `&Dlo("$A1xB")`,`&Dlo("$A1xB")`,$temp
|
||||
vst1.32 {`&Dlo("$A0xB")`[0]}, [$toutptr, :32]!
|
||||
vshr.u64 $temp,`&Dlo("$A1xB")`,#16
|
||||
vadd.u64 `&Dhi("$A1xB")`,`&Dhi("$A1xB")`,$temp
|
||||
vshr.u64 $temp,`&Dhi("$A1xB")`,#16
|
||||
vzip.16 `&Dlo("$A1xB")`,`&Dhi("$A1xB")`
|
||||
|
||||
vadd.u64 `&Dlo("$A2xB")`,`&Dlo("$A2xB")`,$temp
|
||||
vst1.32 {`&Dlo("$A1xB")`[0]}, [$toutptr, :32]!
|
||||
vshr.u64 $temp,`&Dlo("$A2xB")`,#16
|
||||
vadd.u64 `&Dhi("$A2xB")`,`&Dhi("$A2xB")`,$temp
|
||||
vshr.u64 $temp,`&Dhi("$A2xB")`,#16
|
||||
vzip.16 `&Dlo("$A2xB")`,`&Dhi("$A2xB")`
|
||||
|
||||
vadd.u64 `&Dlo("$A3xB")`,`&Dlo("$A3xB")`,$temp
|
||||
vst1.32 {`&Dlo("$A2xB")`[0]}, [$toutptr, :32]!
|
||||
vshr.u64 $temp,`&Dlo("$A3xB")`,#16
|
||||
vadd.u64 `&Dhi("$A3xB")`,`&Dhi("$A3xB")`,$temp
|
||||
vshr.u64 $temp,`&Dhi("$A3xB")`,#16
|
||||
vzip.16 `&Dlo("$A3xB")`,`&Dhi("$A3xB")`
|
||||
|
||||
vadd.u64 `&Dlo("$A4xB")`,`&Dlo("$A4xB")`,$temp
|
||||
vst1.32 {`&Dlo("$A3xB")`[0]}, [$toutptr, :32]!
|
||||
vshr.u64 $temp,`&Dlo("$A4xB")`,#16
|
||||
vadd.u64 `&Dhi("$A4xB")`,`&Dhi("$A4xB")`,$temp
|
||||
vshr.u64 $temp,`&Dhi("$A4xB")`,#16
|
||||
vzip.16 `&Dlo("$A4xB")`,`&Dhi("$A4xB")`
|
||||
|
||||
vadd.u64 `&Dlo("$A5xB")`,`&Dlo("$A5xB")`,$temp
|
||||
vst1.32 {`&Dlo("$A4xB")`[0]}, [$toutptr, :32]!
|
||||
vshr.u64 $temp,`&Dlo("$A5xB")`,#16
|
||||
vadd.u64 `&Dhi("$A5xB")`,`&Dhi("$A5xB")`,$temp
|
||||
vshr.u64 $temp,`&Dhi("$A5xB")`,#16
|
||||
vzip.16 `&Dlo("$A5xB")`,`&Dhi("$A5xB")`
|
||||
|
||||
vadd.u64 `&Dlo("$A6xB")`,`&Dlo("$A6xB")`,$temp
|
||||
vst1.32 {`&Dlo("$A5xB")`[0]}, [$toutptr, :32]!
|
||||
vshr.u64 $temp,`&Dlo("$A6xB")`,#16
|
||||
vadd.u64 `&Dhi("$A6xB")`,`&Dhi("$A6xB")`,$temp
|
||||
vld1.64 {$A0xB}, [$tinptr, :128]!
|
||||
vshr.u64 $temp,`&Dhi("$A6xB")`,#16
|
||||
vzip.16 `&Dlo("$A6xB")`,`&Dhi("$A6xB")`
|
||||
|
||||
vadd.u64 `&Dlo("$A7xB")`,`&Dlo("$A7xB")`,$temp
|
||||
vst1.32 {`&Dlo("$A6xB")`[0]}, [$toutptr, :32]!
|
||||
vshr.u64 $temp,`&Dlo("$A7xB")`,#16
|
||||
vadd.u64 `&Dhi("$A7xB")`,`&Dhi("$A7xB")`,$temp
|
||||
vld1.64 {$A1xB-$A2xB}, [$tinptr, :256]!
|
||||
vshr.u64 $temp,`&Dhi("$A7xB")`,#16
|
||||
vzip.16 `&Dlo("$A7xB")`,`&Dhi("$A7xB")`
|
||||
subs $inner,$inner,#8
|
||||
vst1.32 {`&Dlo("$A7xB")`[0]}, [$toutptr, :32]!
|
||||
|
||||
bne .LNEON_tail
|
||||
|
||||
vst1.32 {${temp}[0]}, [$toutptr, :32] @ top-most bit
|
||||
sub $nptr,$nptr,$num,lsl#2 @ rewind $nptr
|
||||
subs $aptr,sp,#0 @ clear carry flag
|
||||
add $bptr,sp,$num,lsl#2
|
||||
|
||||
.LNEON_sub:
|
||||
ldmia $aptr!, {r4-r7}
|
||||
ldmia $nptr!, {r8-r11}
|
||||
sbcs r8, r4,r8
|
||||
sbcs r9, r5,r9
|
||||
sbcs r10,r6,r10
|
||||
sbcs r11,r7,r11
|
||||
teq $aptr,$bptr @ preserves carry
|
||||
stmia $rptr!, {r8-r11}
|
||||
bne .LNEON_sub
|
||||
|
||||
ldr r10, [$aptr] @ load top-most bit
|
||||
veor q0,q0,q0
|
||||
sub r11,$bptr,sp @ this is num*4
|
||||
veor q1,q1,q1
|
||||
mov $aptr,sp
|
||||
sub $rptr,$rptr,r11 @ rewind $rptr
|
||||
mov $nptr,$bptr @ second 3/4th of frame
|
||||
sbcs r10,r10,#0 @ result is carry flag
|
||||
|
||||
.LNEON_copy_n_zap:
|
||||
ldmia $aptr!, {r4-r7}
|
||||
ldmia $rptr, {r8-r11}
|
||||
movcc r8, r4
|
||||
vst1.64 {q0-q1}, [$nptr,:256]! @ wipe
|
||||
movcc r9, r5
|
||||
movcc r10,r6
|
||||
vst1.64 {q0-q1}, [$nptr,:256]! @ wipe
|
||||
movcc r11,r7
|
||||
ldmia $aptr, {r4-r7}
|
||||
stmia $rptr!, {r8-r11}
|
||||
sub $aptr,$aptr,#16
|
||||
ldmia $rptr, {r8-r11}
|
||||
movcc r8, r4
|
||||
vst1.64 {q0-q1}, [$aptr,:256]! @ wipe
|
||||
movcc r9, r5
|
||||
movcc r10,r6
|
||||
vst1.64 {q0-q1}, [$nptr,:256]! @ wipe
|
||||
movcc r11,r7
|
||||
teq $aptr,$bptr @ preserves carry
|
||||
stmia $rptr!, {r8-r11}
|
||||
bne .LNEON_copy_n_zap
|
||||
|
||||
sub sp,ip,#96
|
||||
vldmia sp!,{d8-d15}
|
||||
ldmia sp!,{r4-r11}
|
||||
ret @ bx lr
|
||||
.size bn_mul8x_mont_neon,.-bn_mul8x_mont_neon
|
||||
#endif
|
||||
___
|
||||
}
|
||||
$code.=<<___;
|
||||
.asciz "Montgomery multiplication for ARMv4/NEON, CRYPTOGAMS by <appro\@openssl.org>"
|
||||
.align 2
|
||||
#if __ARM_MAX_ARCH__>=7
|
||||
.comm OPENSSL_armcap_P,4,4
|
||||
.hidden OPENSSL_armcap_P
|
||||
#endif
|
||||
___
|
||||
|
||||
$code =~ s/\`([^\`]*)\`/eval $1/gem;
|
||||
$code =~ s/\bbx\s+lr\b/.word\t0xe12fff1e/gm; # make it possible to compile with -march=armv4
|
||||
$code =~ s/\bret\b/bx lr/gm;
|
||||
print $code;
|
||||
close STDOUT;
|
||||
@@ -1,532 +0,0 @@
|
||||
/* x86_64 BIGNUM accelerator version 0.1, December 2002.
|
||||
*
|
||||
* Implemented by Andy Polyakov <appro@fy.chalmers.se> for the OpenSSL
|
||||
* project.
|
||||
*
|
||||
* Rights for redistribution and usage in source and binary forms are
|
||||
* granted according to the OpenSSL license. Warranty of any kind is
|
||||
* disclaimed.
|
||||
*
|
||||
* Q. Version 0.1? It doesn't sound like Andy, he used to assign real
|
||||
* versions, like 1.0...
|
||||
* A. Well, that's because this code is basically a quick-n-dirty
|
||||
* proof-of-concept hack. As you can see it's implemented with
|
||||
* inline assembler, which means that you're bound to GCC and that
|
||||
* there might be enough room for further improvement.
|
||||
*
|
||||
* Q. Why inline assembler?
|
||||
* A. x86_64 features own ABI which I'm not familiar with. This is
|
||||
* why I decided to let the compiler take care of subroutine
|
||||
* prologue/epilogue as well as register allocation. For reference.
|
||||
* Win64 implements different ABI for AMD64, different from Linux.
|
||||
*
|
||||
* Q. How much faster does it get?
|
||||
* A. 'apps/openssl speed rsa dsa' output with no-asm:
|
||||
*
|
||||
* sign verify sign/s verify/s
|
||||
* rsa 512 bits 0.0006s 0.0001s 1683.8 18456.2
|
||||
* rsa 1024 bits 0.0028s 0.0002s 356.0 6407.0
|
||||
* rsa 2048 bits 0.0172s 0.0005s 58.0 1957.8
|
||||
* rsa 4096 bits 0.1155s 0.0018s 8.7 555.6
|
||||
* sign verify sign/s verify/s
|
||||
* dsa 512 bits 0.0005s 0.0006s 2100.8 1768.3
|
||||
* dsa 1024 bits 0.0014s 0.0018s 692.3 559.2
|
||||
* dsa 2048 bits 0.0049s 0.0061s 204.7 165.0
|
||||
*
|
||||
* 'apps/openssl speed rsa dsa' output with this module:
|
||||
*
|
||||
* sign verify sign/s verify/s
|
||||
* rsa 512 bits 0.0004s 0.0000s 2767.1 33297.9
|
||||
* rsa 1024 bits 0.0012s 0.0001s 867.4 14674.7
|
||||
* rsa 2048 bits 0.0061s 0.0002s 164.0 5270.0
|
||||
* rsa 4096 bits 0.0384s 0.0006s 26.1 1650.8
|
||||
* sign verify sign/s verify/s
|
||||
* dsa 512 bits 0.0002s 0.0003s 4442.2 3786.3
|
||||
* dsa 1024 bits 0.0005s 0.0007s 1835.1 1497.4
|
||||
* dsa 2048 bits 0.0016s 0.0020s 620.4 504.6
|
||||
*
|
||||
* For the reference. IA-32 assembler implementation performs
|
||||
* very much like 64-bit code compiled with no-asm on the same
|
||||
* machine.
|
||||
*/
|
||||
|
||||
#include <openssl/bn.h>
|
||||
|
||||
/* TODO(davidben): Get this file working on Windows x64. */
|
||||
#if !defined(OPENSSL_NO_ASM) && defined(OPENSSL_X86_64) && defined(__GNUC__)
|
||||
|
||||
#include "../internal.h"
|
||||
|
||||
|
||||
#undef mul
|
||||
#undef mul_add
|
||||
|
||||
#define asm __asm__
|
||||
|
||||
/*
|
||||
* "m"(a), "+m"(r) is the way to favor DirectPath µ-code;
|
||||
* "g"(0) let the compiler to decide where does it
|
||||
* want to keep the value of zero;
|
||||
*/
|
||||
#define mul_add(r, a, word, carry) \
|
||||
do { \
|
||||
register BN_ULONG high, low; \
|
||||
asm("mulq %3" : "=a"(low), "=d"(high) : "a"(word), "m"(a) : "cc"); \
|
||||
asm("addq %2,%0; adcq %3,%1" \
|
||||
: "+r"(carry), "+d"(high) \
|
||||
: "a"(low), "g"(0) \
|
||||
: "cc"); \
|
||||
asm("addq %2,%0; adcq %3,%1" \
|
||||
: "+m"(r), "+d"(high) \
|
||||
: "r"(carry), "g"(0) \
|
||||
: "cc"); \
|
||||
(carry) = high; \
|
||||
} while (0)
|
||||
|
||||
#define mul(r, a, word, carry) \
|
||||
do { \
|
||||
register BN_ULONG high, low; \
|
||||
asm("mulq %3" : "=a"(low), "=d"(high) : "a"(word), "g"(a) : "cc"); \
|
||||
asm("addq %2,%0; adcq %3,%1" \
|
||||
: "+r"(carry), "+d"(high) \
|
||||
: "a"(low), "g"(0) \
|
||||
: "cc"); \
|
||||
(r) = (carry); \
|
||||
(carry) = high; \
|
||||
} while (0)
|
||||
#undef sqr
|
||||
#define sqr(r0, r1, a) asm("mulq %2" : "=a"(r0), "=d"(r1) : "a"(a) : "cc");
|
||||
|
||||
BN_ULONG bn_mul_add_words(BN_ULONG *rp, const BN_ULONG *ap, int num,
|
||||
BN_ULONG w) {
|
||||
BN_ULONG c1 = 0;
|
||||
|
||||
if (num <= 0) {
|
||||
return (c1);
|
||||
}
|
||||
|
||||
while (num & ~3) {
|
||||
mul_add(rp[0], ap[0], w, c1);
|
||||
mul_add(rp[1], ap[1], w, c1);
|
||||
mul_add(rp[2], ap[2], w, c1);
|
||||
mul_add(rp[3], ap[3], w, c1);
|
||||
ap += 4;
|
||||
rp += 4;
|
||||
num -= 4;
|
||||
}
|
||||
if (num) {
|
||||
mul_add(rp[0], ap[0], w, c1);
|
||||
if (--num == 0) {
|
||||
return c1;
|
||||
}
|
||||
mul_add(rp[1], ap[1], w, c1);
|
||||
if (--num == 0) {
|
||||
return c1;
|
||||
}
|
||||
mul_add(rp[2], ap[2], w, c1);
|
||||
return c1;
|
||||
}
|
||||
|
||||
return c1;
|
||||
}
|
||||
|
||||
BN_ULONG bn_mul_words(BN_ULONG *rp, const BN_ULONG *ap, int num, BN_ULONG w) {
|
||||
BN_ULONG c1 = 0;
|
||||
|
||||
if (num <= 0) {
|
||||
return c1;
|
||||
}
|
||||
|
||||
while (num & ~3) {
|
||||
mul(rp[0], ap[0], w, c1);
|
||||
mul(rp[1], ap[1], w, c1);
|
||||
mul(rp[2], ap[2], w, c1);
|
||||
mul(rp[3], ap[3], w, c1);
|
||||
ap += 4;
|
||||
rp += 4;
|
||||
num -= 4;
|
||||
}
|
||||
if (num) {
|
||||
mul(rp[0], ap[0], w, c1);
|
||||
if (--num == 0) {
|
||||
return c1;
|
||||
}
|
||||
mul(rp[1], ap[1], w, c1);
|
||||
if (--num == 0) {
|
||||
return c1;
|
||||
}
|
||||
mul(rp[2], ap[2], w, c1);
|
||||
}
|
||||
return c1;
|
||||
}
|
||||
|
||||
void bn_sqr_words(BN_ULONG *r, const BN_ULONG *a, int n) {
|
||||
if (n <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
while (n & ~3) {
|
||||
sqr(r[0], r[1], a[0]);
|
||||
sqr(r[2], r[3], a[1]);
|
||||
sqr(r[4], r[5], a[2]);
|
||||
sqr(r[6], r[7], a[3]);
|
||||
a += 4;
|
||||
r += 8;
|
||||
n -= 4;
|
||||
}
|
||||
if (n) {
|
||||
sqr(r[0], r[1], a[0]);
|
||||
if (--n == 0) {
|
||||
return;
|
||||
}
|
||||
sqr(r[2], r[3], a[1]);
|
||||
if (--n == 0) {
|
||||
return;
|
||||
}
|
||||
sqr(r[4], r[5], a[2]);
|
||||
}
|
||||
}
|
||||
|
||||
BN_ULONG bn_add_words(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
|
||||
int n) {
|
||||
BN_ULONG ret;
|
||||
size_t i = 0;
|
||||
|
||||
if (n <= 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
asm volatile (
|
||||
" subq %0,%0 \n" /* clear carry */
|
||||
" jmp 1f \n"
|
||||
".p2align 4 \n"
|
||||
"1: movq (%4,%2,8),%0 \n"
|
||||
" adcq (%5,%2,8),%0 \n"
|
||||
" movq %0,(%3,%2,8) \n"
|
||||
" lea 1(%2),%2 \n"
|
||||
" loop 1b \n"
|
||||
" sbbq %0,%0 \n"
|
||||
: "=&r"(ret), "+c"(n), "+r"(i)
|
||||
: "r"(rp), "r"(ap), "r"(bp)
|
||||
: "cc", "memory");
|
||||
|
||||
return ret & 1;
|
||||
}
|
||||
|
||||
BN_ULONG bn_sub_words(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
|
||||
int n) {
|
||||
BN_ULONG ret;
|
||||
size_t i = 0;
|
||||
|
||||
if (n <= 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
asm volatile (
|
||||
" subq %0,%0 \n" /* clear borrow */
|
||||
" jmp 1f \n"
|
||||
".p2align 4 \n"
|
||||
"1: movq (%4,%2,8),%0 \n"
|
||||
" sbbq (%5,%2,8),%0 \n"
|
||||
" movq %0,(%3,%2,8) \n"
|
||||
" lea 1(%2),%2 \n"
|
||||
" loop 1b \n"
|
||||
" sbbq %0,%0 \n"
|
||||
: "=&r"(ret), "+c"(n), "+r"(i)
|
||||
: "r"(rp), "r"(ap), "r"(bp)
|
||||
: "cc", "memory");
|
||||
|
||||
return ret & 1;
|
||||
}
|
||||
|
||||
/* mul_add_c(a,b,c0,c1,c2) -- c+=a*b for three word number c=(c2,c1,c0) */
|
||||
/* mul_add_c2(a,b,c0,c1,c2) -- c+=2*a*b for three word number c=(c2,c1,c0) */
|
||||
/* sqr_add_c(a,i,c0,c1,c2) -- c+=a[i]^2 for three word number c=(c2,c1,c0) */
|
||||
/* sqr_add_c2(a,i,c0,c1,c2) -- c+=2*a[i]*a[j] for three word number c=(c2,c1,c0)
|
||||
*/
|
||||
|
||||
/* Keep in mind that carrying into high part of multiplication result can not
|
||||
* overflow, because it cannot be all-ones. */
|
||||
#define mul_add_c(a, b, c0, c1, c2) \
|
||||
do { \
|
||||
BN_ULONG t1, t2; \
|
||||
asm("mulq %3" : "=a"(t1), "=d"(t2) : "a"(a), "m"(b) : "cc"); \
|
||||
asm("addq %3,%0; adcq %4,%1; adcq %5,%2" \
|
||||
: "+r"(c0), "+r"(c1), "+r"(c2) \
|
||||
: "r"(t1), "r"(t2), "g"(0) \
|
||||
: "cc"); \
|
||||
} while (0)
|
||||
|
||||
#define sqr_add_c(a, i, c0, c1, c2) \
|
||||
do { \
|
||||
BN_ULONG t1, t2; \
|
||||
asm("mulq %2" : "=a"(t1), "=d"(t2) : "a"((a)[i]) : "cc"); \
|
||||
asm("addq %3,%0; adcq %4,%1; adcq %5,%2" \
|
||||
: "+r"(c0), "+r"(c1), "+r"(c2) \
|
||||
: "r"(t1), "r"(t2), "g"(0) \
|
||||
: "cc"); \
|
||||
} while (0)
|
||||
|
||||
#define mul_add_c2(a, b, c0, c1, c2) \
|
||||
do { \
|
||||
BN_ULONG t1, t2; \
|
||||
asm("mulq %3" : "=a"(t1), "=d"(t2) : "a"(a), "m"(b) : "cc"); \
|
||||
asm("addq %3,%0; adcq %4,%1; adcq %5,%2" \
|
||||
: "+r"(c0), "+r"(c1), "+r"(c2) \
|
||||
: "r"(t1), "r"(t2), "g"(0) \
|
||||
: "cc"); \
|
||||
asm("addq %3,%0; adcq %4,%1; adcq %5,%2" \
|
||||
: "+r"(c0), "+r"(c1), "+r"(c2) \
|
||||
: "r"(t1), "r"(t2), "g"(0) \
|
||||
: "cc"); \
|
||||
} while (0)
|
||||
|
||||
#define sqr_add_c2(a, i, j, c0, c1, c2) mul_add_c2((a)[i], (a)[j], c0, c1, c2)
|
||||
|
||||
void bn_mul_comba8(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b) {
|
||||
BN_ULONG c1, c2, c3;
|
||||
|
||||
c1 = 0;
|
||||
c2 = 0;
|
||||
c3 = 0;
|
||||
mul_add_c(a[0], b[0], c1, c2, c3);
|
||||
r[0] = c1;
|
||||
c1 = 0;
|
||||
mul_add_c(a[0], b[1], c2, c3, c1);
|
||||
mul_add_c(a[1], b[0], c2, c3, c1);
|
||||
r[1] = c2;
|
||||
c2 = 0;
|
||||
mul_add_c(a[2], b[0], c3, c1, c2);
|
||||
mul_add_c(a[1], b[1], c3, c1, c2);
|
||||
mul_add_c(a[0], b[2], c3, c1, c2);
|
||||
r[2] = c3;
|
||||
c3 = 0;
|
||||
mul_add_c(a[0], b[3], c1, c2, c3);
|
||||
mul_add_c(a[1], b[2], c1, c2, c3);
|
||||
mul_add_c(a[2], b[1], c1, c2, c3);
|
||||
mul_add_c(a[3], b[0], c1, c2, c3);
|
||||
r[3] = c1;
|
||||
c1 = 0;
|
||||
mul_add_c(a[4], b[0], c2, c3, c1);
|
||||
mul_add_c(a[3], b[1], c2, c3, c1);
|
||||
mul_add_c(a[2], b[2], c2, c3, c1);
|
||||
mul_add_c(a[1], b[3], c2, c3, c1);
|
||||
mul_add_c(a[0], b[4], c2, c3, c1);
|
||||
r[4] = c2;
|
||||
c2 = 0;
|
||||
mul_add_c(a[0], b[5], c3, c1, c2);
|
||||
mul_add_c(a[1], b[4], c3, c1, c2);
|
||||
mul_add_c(a[2], b[3], c3, c1, c2);
|
||||
mul_add_c(a[3], b[2], c3, c1, c2);
|
||||
mul_add_c(a[4], b[1], c3, c1, c2);
|
||||
mul_add_c(a[5], b[0], c3, c1, c2);
|
||||
r[5] = c3;
|
||||
c3 = 0;
|
||||
mul_add_c(a[6], b[0], c1, c2, c3);
|
||||
mul_add_c(a[5], b[1], c1, c2, c3);
|
||||
mul_add_c(a[4], b[2], c1, c2, c3);
|
||||
mul_add_c(a[3], b[3], c1, c2, c3);
|
||||
mul_add_c(a[2], b[4], c1, c2, c3);
|
||||
mul_add_c(a[1], b[5], c1, c2, c3);
|
||||
mul_add_c(a[0], b[6], c1, c2, c3);
|
||||
r[6] = c1;
|
||||
c1 = 0;
|
||||
mul_add_c(a[0], b[7], c2, c3, c1);
|
||||
mul_add_c(a[1], b[6], c2, c3, c1);
|
||||
mul_add_c(a[2], b[5], c2, c3, c1);
|
||||
mul_add_c(a[3], b[4], c2, c3, c1);
|
||||
mul_add_c(a[4], b[3], c2, c3, c1);
|
||||
mul_add_c(a[5], b[2], c2, c3, c1);
|
||||
mul_add_c(a[6], b[1], c2, c3, c1);
|
||||
mul_add_c(a[7], b[0], c2, c3, c1);
|
||||
r[7] = c2;
|
||||
c2 = 0;
|
||||
mul_add_c(a[7], b[1], c3, c1, c2);
|
||||
mul_add_c(a[6], b[2], c3, c1, c2);
|
||||
mul_add_c(a[5], b[3], c3, c1, c2);
|
||||
mul_add_c(a[4], b[4], c3, c1, c2);
|
||||
mul_add_c(a[3], b[5], c3, c1, c2);
|
||||
mul_add_c(a[2], b[6], c3, c1, c2);
|
||||
mul_add_c(a[1], b[7], c3, c1, c2);
|
||||
r[8] = c3;
|
||||
c3 = 0;
|
||||
mul_add_c(a[2], b[7], c1, c2, c3);
|
||||
mul_add_c(a[3], b[6], c1, c2, c3);
|
||||
mul_add_c(a[4], b[5], c1, c2, c3);
|
||||
mul_add_c(a[5], b[4], c1, c2, c3);
|
||||
mul_add_c(a[6], b[3], c1, c2, c3);
|
||||
mul_add_c(a[7], b[2], c1, c2, c3);
|
||||
r[9] = c1;
|
||||
c1 = 0;
|
||||
mul_add_c(a[7], b[3], c2, c3, c1);
|
||||
mul_add_c(a[6], b[4], c2, c3, c1);
|
||||
mul_add_c(a[5], b[5], c2, c3, c1);
|
||||
mul_add_c(a[4], b[6], c2, c3, c1);
|
||||
mul_add_c(a[3], b[7], c2, c3, c1);
|
||||
r[10] = c2;
|
||||
c2 = 0;
|
||||
mul_add_c(a[4], b[7], c3, c1, c2);
|
||||
mul_add_c(a[5], b[6], c3, c1, c2);
|
||||
mul_add_c(a[6], b[5], c3, c1, c2);
|
||||
mul_add_c(a[7], b[4], c3, c1, c2);
|
||||
r[11] = c3;
|
||||
c3 = 0;
|
||||
mul_add_c(a[7], b[5], c1, c2, c3);
|
||||
mul_add_c(a[6], b[6], c1, c2, c3);
|
||||
mul_add_c(a[5], b[7], c1, c2, c3);
|
||||
r[12] = c1;
|
||||
c1 = 0;
|
||||
mul_add_c(a[6], b[7], c2, c3, c1);
|
||||
mul_add_c(a[7], b[6], c2, c3, c1);
|
||||
r[13] = c2;
|
||||
c2 = 0;
|
||||
mul_add_c(a[7], b[7], c3, c1, c2);
|
||||
r[14] = c3;
|
||||
r[15] = c1;
|
||||
}
|
||||
|
||||
void bn_mul_comba4(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b) {
|
||||
BN_ULONG c1, c2, c3;
|
||||
|
||||
c1 = 0;
|
||||
c2 = 0;
|
||||
c3 = 0;
|
||||
mul_add_c(a[0], b[0], c1, c2, c3);
|
||||
r[0] = c1;
|
||||
c1 = 0;
|
||||
mul_add_c(a[0], b[1], c2, c3, c1);
|
||||
mul_add_c(a[1], b[0], c2, c3, c1);
|
||||
r[1] = c2;
|
||||
c2 = 0;
|
||||
mul_add_c(a[2], b[0], c3, c1, c2);
|
||||
mul_add_c(a[1], b[1], c3, c1, c2);
|
||||
mul_add_c(a[0], b[2], c3, c1, c2);
|
||||
r[2] = c3;
|
||||
c3 = 0;
|
||||
mul_add_c(a[0], b[3], c1, c2, c3);
|
||||
mul_add_c(a[1], b[2], c1, c2, c3);
|
||||
mul_add_c(a[2], b[1], c1, c2, c3);
|
||||
mul_add_c(a[3], b[0], c1, c2, c3);
|
||||
r[3] = c1;
|
||||
c1 = 0;
|
||||
mul_add_c(a[3], b[1], c2, c3, c1);
|
||||
mul_add_c(a[2], b[2], c2, c3, c1);
|
||||
mul_add_c(a[1], b[3], c2, c3, c1);
|
||||
r[4] = c2;
|
||||
c2 = 0;
|
||||
mul_add_c(a[2], b[3], c3, c1, c2);
|
||||
mul_add_c(a[3], b[2], c3, c1, c2);
|
||||
r[5] = c3;
|
||||
c3 = 0;
|
||||
mul_add_c(a[3], b[3], c1, c2, c3);
|
||||
r[6] = c1;
|
||||
r[7] = c2;
|
||||
}
|
||||
|
||||
void bn_sqr_comba8(BN_ULONG *r, const BN_ULONG *a) {
|
||||
BN_ULONG c1, c2, c3;
|
||||
|
||||
c1 = 0;
|
||||
c2 = 0;
|
||||
c3 = 0;
|
||||
sqr_add_c(a, 0, c1, c2, c3);
|
||||
r[0] = c1;
|
||||
c1 = 0;
|
||||
sqr_add_c2(a, 1, 0, c2, c3, c1);
|
||||
r[1] = c2;
|
||||
c2 = 0;
|
||||
sqr_add_c(a, 1, c3, c1, c2);
|
||||
sqr_add_c2(a, 2, 0, c3, c1, c2);
|
||||
r[2] = c3;
|
||||
c3 = 0;
|
||||
sqr_add_c2(a, 3, 0, c1, c2, c3);
|
||||
sqr_add_c2(a, 2, 1, c1, c2, c3);
|
||||
r[3] = c1;
|
||||
c1 = 0;
|
||||
sqr_add_c(a, 2, c2, c3, c1);
|
||||
sqr_add_c2(a, 3, 1, c2, c3, c1);
|
||||
sqr_add_c2(a, 4, 0, c2, c3, c1);
|
||||
r[4] = c2;
|
||||
c2 = 0;
|
||||
sqr_add_c2(a, 5, 0, c3, c1, c2);
|
||||
sqr_add_c2(a, 4, 1, c3, c1, c2);
|
||||
sqr_add_c2(a, 3, 2, c3, c1, c2);
|
||||
r[5] = c3;
|
||||
c3 = 0;
|
||||
sqr_add_c(a, 3, c1, c2, c3);
|
||||
sqr_add_c2(a, 4, 2, c1, c2, c3);
|
||||
sqr_add_c2(a, 5, 1, c1, c2, c3);
|
||||
sqr_add_c2(a, 6, 0, c1, c2, c3);
|
||||
r[6] = c1;
|
||||
c1 = 0;
|
||||
sqr_add_c2(a, 7, 0, c2, c3, c1);
|
||||
sqr_add_c2(a, 6, 1, c2, c3, c1);
|
||||
sqr_add_c2(a, 5, 2, c2, c3, c1);
|
||||
sqr_add_c2(a, 4, 3, c2, c3, c1);
|
||||
r[7] = c2;
|
||||
c2 = 0;
|
||||
sqr_add_c(a, 4, c3, c1, c2);
|
||||
sqr_add_c2(a, 5, 3, c3, c1, c2);
|
||||
sqr_add_c2(a, 6, 2, c3, c1, c2);
|
||||
sqr_add_c2(a, 7, 1, c3, c1, c2);
|
||||
r[8] = c3;
|
||||
c3 = 0;
|
||||
sqr_add_c2(a, 7, 2, c1, c2, c3);
|
||||
sqr_add_c2(a, 6, 3, c1, c2, c3);
|
||||
sqr_add_c2(a, 5, 4, c1, c2, c3);
|
||||
r[9] = c1;
|
||||
c1 = 0;
|
||||
sqr_add_c(a, 5, c2, c3, c1);
|
||||
sqr_add_c2(a, 6, 4, c2, c3, c1);
|
||||
sqr_add_c2(a, 7, 3, c2, c3, c1);
|
||||
r[10] = c2;
|
||||
c2 = 0;
|
||||
sqr_add_c2(a, 7, 4, c3, c1, c2);
|
||||
sqr_add_c2(a, 6, 5, c3, c1, c2);
|
||||
r[11] = c3;
|
||||
c3 = 0;
|
||||
sqr_add_c(a, 6, c1, c2, c3);
|
||||
sqr_add_c2(a, 7, 5, c1, c2, c3);
|
||||
r[12] = c1;
|
||||
c1 = 0;
|
||||
sqr_add_c2(a, 7, 6, c2, c3, c1);
|
||||
r[13] = c2;
|
||||
c2 = 0;
|
||||
sqr_add_c(a, 7, c3, c1, c2);
|
||||
r[14] = c3;
|
||||
r[15] = c1;
|
||||
}
|
||||
|
||||
void bn_sqr_comba4(BN_ULONG *r, const BN_ULONG *a) {
|
||||
BN_ULONG c1, c2, c3;
|
||||
|
||||
c1 = 0;
|
||||
c2 = 0;
|
||||
c3 = 0;
|
||||
sqr_add_c(a, 0, c1, c2, c3);
|
||||
r[0] = c1;
|
||||
c1 = 0;
|
||||
sqr_add_c2(a, 1, 0, c2, c3, c1);
|
||||
r[1] = c2;
|
||||
c2 = 0;
|
||||
sqr_add_c(a, 1, c3, c1, c2);
|
||||
sqr_add_c2(a, 2, 0, c3, c1, c2);
|
||||
r[2] = c3;
|
||||
c3 = 0;
|
||||
sqr_add_c2(a, 3, 0, c1, c2, c3);
|
||||
sqr_add_c2(a, 2, 1, c1, c2, c3);
|
||||
r[3] = c1;
|
||||
c1 = 0;
|
||||
sqr_add_c(a, 2, c2, c3, c1);
|
||||
sqr_add_c2(a, 3, 1, c2, c3, c1);
|
||||
r[4] = c2;
|
||||
c2 = 0;
|
||||
sqr_add_c2(a, 3, 2, c3, c1, c2);
|
||||
r[5] = c3;
|
||||
c3 = 0;
|
||||
sqr_add_c(a, 3, c1, c2, c3);
|
||||
r[6] = c1;
|
||||
r[7] = c2;
|
||||
}
|
||||
|
||||
#endif /* !NO_ASM && X86_64 && __GNUC__ */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,670 +0,0 @@
|
||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young (eay@cryptsoft.com).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young (eay@cryptsoft.com)"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.] */
|
||||
|
||||
#include <openssl/bn.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl/bio.h>
|
||||
#include <openssl/bytestring.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.h>
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
BIGNUM *BN_bin2bn(const uint8_t *in, size_t len, BIGNUM *ret) {
|
||||
size_t num_words;
|
||||
unsigned m;
|
||||
BN_ULONG word = 0;
|
||||
BIGNUM *bn = NULL;
|
||||
|
||||
if (ret == NULL) {
|
||||
ret = bn = BN_new();
|
||||
}
|
||||
|
||||
if (ret == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (len == 0) {
|
||||
ret->top = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
num_words = ((len - 1) / BN_BYTES) + 1;
|
||||
m = (len - 1) % BN_BYTES;
|
||||
if (bn_wexpand(ret, num_words) == NULL) {
|
||||
if (bn) {
|
||||
BN_free(bn);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* |bn_wexpand| must check bounds on |num_words| to write it into
|
||||
* |ret->dmax|. */
|
||||
assert(num_words <= INT_MAX);
|
||||
ret->top = (int)num_words;
|
||||
ret->neg = 0;
|
||||
|
||||
while (len--) {
|
||||
word = (word << 8) | *(in++);
|
||||
if (m-- == 0) {
|
||||
ret->d[--num_words] = word;
|
||||
word = 0;
|
||||
m = BN_BYTES - 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* need to call this due to clear byte at top if avoiding having the top bit
|
||||
* set (-ve number) */
|
||||
bn_correct_top(ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
BIGNUM *BN_le2bn(const uint8_t *in, size_t len, BIGNUM *ret) {
|
||||
BIGNUM *bn = NULL;
|
||||
if (ret == NULL) {
|
||||
bn = BN_new();
|
||||
ret = bn;
|
||||
}
|
||||
|
||||
if (ret == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (len == 0) {
|
||||
ret->top = 0;
|
||||
ret->neg = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Reserve enough space in |ret|. */
|
||||
size_t num_words = ((len - 1) / BN_BYTES) + 1;
|
||||
if (!bn_wexpand(ret, num_words)) {
|
||||
BN_free(bn);
|
||||
return NULL;
|
||||
}
|
||||
ret->top = num_words;
|
||||
|
||||
/* Make sure the top bytes will be zeroed. */
|
||||
ret->d[num_words - 1] = 0;
|
||||
|
||||
/* We only support little-endian platforms, so we can simply memcpy the
|
||||
* internal representation. */
|
||||
OPENSSL_memcpy(ret->d, in, len);
|
||||
|
||||
bn_correct_top(ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
size_t BN_bn2bin(const BIGNUM *in, uint8_t *out) {
|
||||
size_t n, i;
|
||||
BN_ULONG l;
|
||||
|
||||
n = i = BN_num_bytes(in);
|
||||
while (i--) {
|
||||
l = in->d[i / BN_BYTES];
|
||||
*(out++) = (unsigned char)(l >> (8 * (i % BN_BYTES))) & 0xff;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
int BN_bn2le_padded(uint8_t *out, size_t len, const BIGNUM *in) {
|
||||
/* If we don't have enough space, fail out. */
|
||||
size_t num_bytes = BN_num_bytes(in);
|
||||
if (len < num_bytes) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* We only support little-endian platforms, so we can simply memcpy into the
|
||||
* internal representation. */
|
||||
OPENSSL_memcpy(out, in->d, num_bytes);
|
||||
|
||||
/* Pad out the rest of the buffer with zeroes. */
|
||||
OPENSSL_memset(out + num_bytes, 0, len - num_bytes);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* constant_time_select_ulong returns |x| if |v| is 1 and |y| if |v| is 0. Its
|
||||
* behavior is undefined if |v| takes any other value. */
|
||||
static BN_ULONG constant_time_select_ulong(int v, BN_ULONG x, BN_ULONG y) {
|
||||
BN_ULONG mask = v;
|
||||
mask--;
|
||||
|
||||
return (~mask & x) | (mask & y);
|
||||
}
|
||||
|
||||
/* constant_time_le_size_t returns 1 if |x| <= |y| and 0 otherwise. |x| and |y|
|
||||
* must not have their MSBs set. */
|
||||
static int constant_time_le_size_t(size_t x, size_t y) {
|
||||
return ((x - y - 1) >> (sizeof(size_t) * 8 - 1)) & 1;
|
||||
}
|
||||
|
||||
/* read_word_padded returns the |i|'th word of |in|, if it is not out of
|
||||
* bounds. Otherwise, it returns 0. It does so without branches on the size of
|
||||
* |in|, however it necessarily does not have the same memory access pattern. If
|
||||
* the access would be out of bounds, it reads the last word of |in|. |in| must
|
||||
* not be zero. */
|
||||
static BN_ULONG read_word_padded(const BIGNUM *in, size_t i) {
|
||||
/* Read |in->d[i]| if valid. Otherwise, read the last word. */
|
||||
BN_ULONG l = in->d[constant_time_select_ulong(
|
||||
constant_time_le_size_t(in->dmax, i), in->dmax - 1, i)];
|
||||
|
||||
/* Clamp to zero if above |d->top|. */
|
||||
return constant_time_select_ulong(constant_time_le_size_t(in->top, i), 0, l);
|
||||
}
|
||||
|
||||
int BN_bn2bin_padded(uint8_t *out, size_t len, const BIGNUM *in) {
|
||||
/* Special case for |in| = 0. Just branch as the probability is negligible. */
|
||||
if (BN_is_zero(in)) {
|
||||
OPENSSL_memset(out, 0, len);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Check if the integer is too big. This case can exit early in non-constant
|
||||
* time. */
|
||||
if ((size_t)in->top > (len + (BN_BYTES - 1)) / BN_BYTES) {
|
||||
return 0;
|
||||
}
|
||||
if ((len % BN_BYTES) != 0) {
|
||||
BN_ULONG l = read_word_padded(in, len / BN_BYTES);
|
||||
if (l >> (8 * (len % BN_BYTES)) != 0) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Write the bytes out one by one. Serialization is done without branching on
|
||||
* the bits of |in| or on |in->top|, but if the routine would otherwise read
|
||||
* out of bounds, the memory access pattern can't be fixed. However, for an
|
||||
* RSA key of size a multiple of the word size, the probability of BN_BYTES
|
||||
* leading zero octets is low.
|
||||
*
|
||||
* See Falko Stenzke, "Manger's Attack revisited", ICICS 2010. */
|
||||
size_t i = len;
|
||||
while (i--) {
|
||||
BN_ULONG l = read_word_padded(in, i / BN_BYTES);
|
||||
*(out++) = (uint8_t)(l >> (8 * (i % BN_BYTES))) & 0xff;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int BN_bn2cbb_padded(CBB *out, size_t len, const BIGNUM *in) {
|
||||
uint8_t *ptr;
|
||||
return CBB_add_space(out, &ptr, len) && BN_bn2bin_padded(ptr, len, in);
|
||||
}
|
||||
|
||||
static const char hextable[] = "0123456789abcdef";
|
||||
|
||||
char *BN_bn2hex(const BIGNUM *bn) {
|
||||
char *buf = OPENSSL_malloc(1 /* leading '-' */ + 1 /* zero is non-empty */ +
|
||||
bn->top * BN_BYTES * 2 + 1 /* trailing NUL */);
|
||||
if (buf == NULL) {
|
||||
OPENSSL_PUT_ERROR(BN, ERR_R_MALLOC_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *p = buf;
|
||||
if (bn->neg) {
|
||||
*(p++) = '-';
|
||||
}
|
||||
|
||||
if (BN_is_zero(bn)) {
|
||||
*(p++) = '0';
|
||||
}
|
||||
|
||||
int z = 0;
|
||||
for (int i = bn->top - 1; i >= 0; i--) {
|
||||
for (int j = BN_BITS2 - 8; j >= 0; j -= 8) {
|
||||
/* strip leading zeros */
|
||||
int v = ((int)(bn->d[i] >> (long)j)) & 0xff;
|
||||
if (z || v != 0) {
|
||||
*(p++) = hextable[v >> 4];
|
||||
*(p++) = hextable[v & 0x0f];
|
||||
z = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
*p = '\0';
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
/* decode_hex decodes |in_len| bytes of hex data from |in| and updates |bn|. */
|
||||
static int decode_hex(BIGNUM *bn, const char *in, int in_len) {
|
||||
if (in_len > INT_MAX/4) {
|
||||
OPENSSL_PUT_ERROR(BN, BN_R_BIGNUM_TOO_LONG);
|
||||
return 0;
|
||||
}
|
||||
/* |in_len| is the number of hex digits. */
|
||||
if (bn_expand(bn, in_len * 4) == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int i = 0;
|
||||
while (in_len > 0) {
|
||||
/* Decode one |BN_ULONG| at a time. */
|
||||
int todo = BN_BYTES * 2;
|
||||
if (todo > in_len) {
|
||||
todo = in_len;
|
||||
}
|
||||
|
||||
BN_ULONG word = 0;
|
||||
int j;
|
||||
for (j = todo; j > 0; j--) {
|
||||
char c = in[in_len - j];
|
||||
|
||||
BN_ULONG hex;
|
||||
if (c >= '0' && c <= '9') {
|
||||
hex = c - '0';
|
||||
} else if (c >= 'a' && c <= 'f') {
|
||||
hex = c - 'a' + 10;
|
||||
} else if (c >= 'A' && c <= 'F') {
|
||||
hex = c - 'A' + 10;
|
||||
} else {
|
||||
hex = 0;
|
||||
/* This shouldn't happen. The caller checks |isxdigit|. */
|
||||
assert(0);
|
||||
}
|
||||
word = (word << 4) | hex;
|
||||
}
|
||||
|
||||
bn->d[i++] = word;
|
||||
in_len -= todo;
|
||||
}
|
||||
assert(i <= bn->dmax);
|
||||
bn->top = i;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* decode_dec decodes |in_len| bytes of decimal data from |in| and updates |bn|. */
|
||||
static int decode_dec(BIGNUM *bn, const char *in, int in_len) {
|
||||
int i, j;
|
||||
BN_ULONG l = 0;
|
||||
|
||||
/* Decode |BN_DEC_NUM| digits at a time. */
|
||||
j = BN_DEC_NUM - (in_len % BN_DEC_NUM);
|
||||
if (j == BN_DEC_NUM) {
|
||||
j = 0;
|
||||
}
|
||||
l = 0;
|
||||
for (i = 0; i < in_len; i++) {
|
||||
l *= 10;
|
||||
l += in[i] - '0';
|
||||
if (++j == BN_DEC_NUM) {
|
||||
if (!BN_mul_word(bn, BN_DEC_CONV) ||
|
||||
!BN_add_word(bn, l)) {
|
||||
return 0;
|
||||
}
|
||||
l = 0;
|
||||
j = 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
typedef int (*decode_func) (BIGNUM *bn, const char *in, int in_len);
|
||||
typedef int (*char_test_func) (int c);
|
||||
|
||||
static int bn_x2bn(BIGNUM **outp, const char *in, decode_func decode, char_test_func want_char) {
|
||||
BIGNUM *ret = NULL;
|
||||
int neg = 0, i;
|
||||
int num;
|
||||
|
||||
if (in == NULL || *in == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (*in == '-') {
|
||||
neg = 1;
|
||||
in++;
|
||||
}
|
||||
|
||||
for (i = 0; want_char((unsigned char)in[i]) && i + neg < INT_MAX; i++) {}
|
||||
|
||||
num = i + neg;
|
||||
if (outp == NULL) {
|
||||
return num;
|
||||
}
|
||||
|
||||
/* in is the start of the hex digits, and it is 'i' long */
|
||||
if (*outp == NULL) {
|
||||
ret = BN_new();
|
||||
if (ret == NULL) {
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
ret = *outp;
|
||||
BN_zero(ret);
|
||||
}
|
||||
|
||||
if (!decode(ret, in, i)) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
bn_correct_top(ret);
|
||||
if (!BN_is_zero(ret)) {
|
||||
ret->neg = neg;
|
||||
}
|
||||
|
||||
*outp = ret;
|
||||
return num;
|
||||
|
||||
err:
|
||||
if (*outp == NULL) {
|
||||
BN_free(ret);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int BN_hex2bn(BIGNUM **outp, const char *in) {
|
||||
return bn_x2bn(outp, in, decode_hex, isxdigit);
|
||||
}
|
||||
|
||||
char *BN_bn2dec(const BIGNUM *a) {
|
||||
/* It is easier to print strings little-endian, so we assemble it in reverse
|
||||
* and fix at the end. */
|
||||
BIGNUM *copy = NULL;
|
||||
CBB cbb;
|
||||
if (!CBB_init(&cbb, 16) ||
|
||||
!CBB_add_u8(&cbb, 0 /* trailing NUL */)) {
|
||||
goto cbb_err;
|
||||
}
|
||||
|
||||
if (BN_is_zero(a)) {
|
||||
if (!CBB_add_u8(&cbb, '0')) {
|
||||
goto cbb_err;
|
||||
}
|
||||
} else {
|
||||
copy = BN_dup(a);
|
||||
if (copy == NULL) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
while (!BN_is_zero(copy)) {
|
||||
BN_ULONG word = BN_div_word(copy, BN_DEC_CONV);
|
||||
if (word == (BN_ULONG)-1) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
const int add_leading_zeros = !BN_is_zero(copy);
|
||||
for (int i = 0; i < BN_DEC_NUM && (add_leading_zeros || word != 0); i++) {
|
||||
if (!CBB_add_u8(&cbb, '0' + word % 10)) {
|
||||
goto cbb_err;
|
||||
}
|
||||
word /= 10;
|
||||
}
|
||||
assert(word == 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (BN_is_negative(a) &&
|
||||
!CBB_add_u8(&cbb, '-')) {
|
||||
goto cbb_err;
|
||||
}
|
||||
|
||||
uint8_t *data;
|
||||
size_t len;
|
||||
if (!CBB_finish(&cbb, &data, &len)) {
|
||||
goto cbb_err;
|
||||
}
|
||||
|
||||
/* Reverse the buffer. */
|
||||
for (size_t i = 0; i < len/2; i++) {
|
||||
uint8_t tmp = data[i];
|
||||
data[i] = data[len - 1 - i];
|
||||
data[len - 1 - i] = tmp;
|
||||
}
|
||||
|
||||
BN_free(copy);
|
||||
return (char *)data;
|
||||
|
||||
cbb_err:
|
||||
OPENSSL_PUT_ERROR(BN, ERR_R_MALLOC_FAILURE);
|
||||
err:
|
||||
BN_free(copy);
|
||||
CBB_cleanup(&cbb);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int BN_dec2bn(BIGNUM **outp, const char *in) {
|
||||
return bn_x2bn(outp, in, decode_dec, isdigit);
|
||||
}
|
||||
|
||||
int BN_asc2bn(BIGNUM **outp, const char *in) {
|
||||
const char *const orig_in = in;
|
||||
if (*in == '-') {
|
||||
in++;
|
||||
}
|
||||
|
||||
if (in[0] == '0' && (in[1] == 'X' || in[1] == 'x')) {
|
||||
if (!BN_hex2bn(outp, in+2)) {
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
if (!BN_dec2bn(outp, in)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (*orig_in == '-' && !BN_is_zero(*outp)) {
|
||||
(*outp)->neg = 1;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int BN_print(BIO *bp, const BIGNUM *a) {
|
||||
int i, j, v, z = 0;
|
||||
int ret = 0;
|
||||
|
||||
if (a->neg && BIO_write(bp, "-", 1) != 1) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (BN_is_zero(a) && BIO_write(bp, "0", 1) != 1) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
for (i = a->top - 1; i >= 0; i--) {
|
||||
for (j = BN_BITS2 - 4; j >= 0; j -= 4) {
|
||||
/* strip leading zeros */
|
||||
v = ((int)(a->d[i] >> (long)j)) & 0x0f;
|
||||
if (z || v != 0) {
|
||||
if (BIO_write(bp, &hextable[v], 1) != 1) {
|
||||
goto end;
|
||||
}
|
||||
z = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
ret = 1;
|
||||
|
||||
end:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int BN_print_fp(FILE *fp, const BIGNUM *a) {
|
||||
BIO *b;
|
||||
int ret;
|
||||
|
||||
b = BIO_new(BIO_s_file());
|
||||
if (b == NULL) {
|
||||
return 0;
|
||||
}
|
||||
BIO_set_fp(b, fp, BIO_NOCLOSE);
|
||||
ret = BN_print(b, a);
|
||||
BIO_free(b);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
BN_ULONG BN_get_word(const BIGNUM *bn) {
|
||||
switch (bn->top) {
|
||||
case 0:
|
||||
return 0;
|
||||
case 1:
|
||||
return bn->d[0];
|
||||
default:
|
||||
return BN_MASK2;
|
||||
}
|
||||
}
|
||||
|
||||
int BN_get_u64(const BIGNUM *bn, uint64_t *out) {
|
||||
switch (bn->top) {
|
||||
case 0:
|
||||
*out = 0;
|
||||
return 1;
|
||||
case 1:
|
||||
*out = bn->d[0];
|
||||
return 1;
|
||||
#if defined(OPENSSL_32_BIT)
|
||||
case 2:
|
||||
*out = (uint64_t) bn->d[0] | (((uint64_t) bn->d[1]) << 32);
|
||||
return 1;
|
||||
#endif
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
size_t BN_bn2mpi(const BIGNUM *in, uint8_t *out) {
|
||||
const size_t bits = BN_num_bits(in);
|
||||
const size_t bytes = (bits + 7) / 8;
|
||||
/* If the number of bits is a multiple of 8, i.e. if the MSB is set,
|
||||
* prefix with a zero byte. */
|
||||
int extend = 0;
|
||||
if (bytes != 0 && (bits & 0x07) == 0) {
|
||||
extend = 1;
|
||||
}
|
||||
|
||||
const size_t len = bytes + extend;
|
||||
if (len < bytes ||
|
||||
4 + len < len ||
|
||||
(len & 0xffffffff) != len) {
|
||||
/* If we cannot represent the number then we emit zero as the interface
|
||||
* doesn't allow an error to be signalled. */
|
||||
if (out) {
|
||||
OPENSSL_memset(out, 0, 4);
|
||||
}
|
||||
return 4;
|
||||
}
|
||||
|
||||
if (out == NULL) {
|
||||
return 4 + len;
|
||||
}
|
||||
|
||||
out[0] = len >> 24;
|
||||
out[1] = len >> 16;
|
||||
out[2] = len >> 8;
|
||||
out[3] = len;
|
||||
if (extend) {
|
||||
out[4] = 0;
|
||||
}
|
||||
BN_bn2bin(in, out + 4 + extend);
|
||||
if (in->neg && len > 0) {
|
||||
out[4] |= 0x80;
|
||||
}
|
||||
return len + 4;
|
||||
}
|
||||
|
||||
BIGNUM *BN_mpi2bn(const uint8_t *in, size_t len, BIGNUM *out) {
|
||||
if (len < 4) {
|
||||
OPENSSL_PUT_ERROR(BN, BN_R_BAD_ENCODING);
|
||||
return NULL;
|
||||
}
|
||||
const size_t in_len = ((size_t)in[0] << 24) |
|
||||
((size_t)in[1] << 16) |
|
||||
((size_t)in[2] << 8) |
|
||||
((size_t)in[3]);
|
||||
if (in_len != len - 4) {
|
||||
OPENSSL_PUT_ERROR(BN, BN_R_BAD_ENCODING);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int out_is_alloced = 0;
|
||||
if (out == NULL) {
|
||||
out = BN_new();
|
||||
if (out == NULL) {
|
||||
OPENSSL_PUT_ERROR(BN, ERR_R_MALLOC_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
out_is_alloced = 1;
|
||||
}
|
||||
|
||||
if (in_len == 0) {
|
||||
BN_zero(out);
|
||||
return out;
|
||||
}
|
||||
|
||||
in += 4;
|
||||
if (BN_bin2bn(in, in_len, out) == NULL) {
|
||||
if (out_is_alloced) {
|
||||
BN_free(out);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
out->neg = ((*in) & 0x80) != 0;
|
||||
if (out->neg) {
|
||||
BN_clear_bit(out, BN_num_bits(out) - 1);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
@@ -1,258 +0,0 @@
|
||||
/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young (eay@cryptsoft.com).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young (eay@cryptsoft.com)"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.]
|
||||
*/
|
||||
/* ====================================================================
|
||||
* Copyright (c) 1998-2006 The OpenSSL Project. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. All advertising materials mentioning features or use of this
|
||||
* software must display the following acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
|
||||
*
|
||||
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
|
||||
* endorse or promote products derived from this software without
|
||||
* prior written permission. For written permission, please contact
|
||||
* openssl-core@openssl.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "OpenSSL"
|
||||
* nor may "OpenSSL" appear in their names without prior written
|
||||
* permission of the OpenSSL Project.
|
||||
*
|
||||
* 6. Redistributions of any form whatsoever must retain the following
|
||||
* acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit (http://www.openssl.org/)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
|
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ====================================================================
|
||||
*
|
||||
* This product includes cryptographic software written by Eric Young
|
||||
* (eay@cryptsoft.com). This product includes software written by Tim
|
||||
* Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
*/
|
||||
/* ====================================================================
|
||||
* Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
|
||||
*
|
||||
* Portions of the attached software ("Contribution") are developed by
|
||||
* SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project.
|
||||
*
|
||||
* The Contribution is licensed pursuant to the Eric Young open source
|
||||
* license provided above.
|
||||
*
|
||||
* The binary polynomial arithmetic software is originally written by
|
||||
* Sheueling Chang Shantz and Douglas Stebila of Sun Microsystems
|
||||
* Laboratories. */
|
||||
|
||||
#ifndef OPENSSL_HEADER_BN_INTERNAL_H
|
||||
#define OPENSSL_HEADER_BN_INTERNAL_H
|
||||
|
||||
#include <openssl/base.h>
|
||||
|
||||
#if defined(OPENSSL_X86_64) && defined(_MSC_VER)
|
||||
OPENSSL_MSVC_PRAGMA(warning(push, 3))
|
||||
#include <intrin.h>
|
||||
OPENSSL_MSVC_PRAGMA(warning(pop))
|
||||
#pragma intrinsic(__umulh, _umul128)
|
||||
#endif
|
||||
|
||||
#include "../internal.h"
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* bn_expand acts the same as |bn_wexpand|, but takes a number of bits rather
|
||||
* than a number of words. */
|
||||
BIGNUM *bn_expand(BIGNUM *bn, size_t bits);
|
||||
|
||||
#if defined(OPENSSL_64_BIT)
|
||||
|
||||
#if !defined(_MSC_VER)
|
||||
/* MSVC doesn't support two-word integers on 64-bit. */
|
||||
#define BN_ULLONG uint128_t
|
||||
#endif
|
||||
|
||||
#define BN_BITS2 64
|
||||
#define BN_BYTES 8
|
||||
#define BN_BITS4 32
|
||||
#define BN_MASK2 (0xffffffffffffffffUL)
|
||||
#define BN_MASK2l (0xffffffffUL)
|
||||
#define BN_MASK2h (0xffffffff00000000UL)
|
||||
#define BN_MASK2h1 (0xffffffff80000000UL)
|
||||
#define BN_MONT_CTX_N0_LIMBS 1
|
||||
#define BN_TBIT (0x8000000000000000UL)
|
||||
#define BN_DEC_CONV (10000000000000000000UL)
|
||||
#define BN_DEC_NUM 19
|
||||
#define TOBN(hi, lo) ((BN_ULONG)(hi) << 32 | (lo))
|
||||
|
||||
#elif defined(OPENSSL_32_BIT)
|
||||
|
||||
#define BN_ULLONG uint64_t
|
||||
#define BN_BITS2 32
|
||||
#define BN_BYTES 4
|
||||
#define BN_BITS4 16
|
||||
#define BN_MASK2 (0xffffffffUL)
|
||||
#define BN_MASK2l (0xffffUL)
|
||||
#define BN_MASK2h1 (0xffff8000UL)
|
||||
#define BN_MASK2h (0xffff0000UL)
|
||||
/* On some 32-bit platforms, Montgomery multiplication is done using 64-bit
|
||||
* arithmetic with SIMD instructions. On such platforms, |BN_MONT_CTX::n0|
|
||||
* needs to be two words long. Only certain 32-bit platforms actually make use
|
||||
* of n0[1] and shorter R value would suffice for the others. However,
|
||||
* currently only the assembly files know which is which. */
|
||||
#define BN_MONT_CTX_N0_LIMBS 2
|
||||
#define BN_TBIT (0x80000000UL)
|
||||
#define BN_DEC_CONV (1000000000UL)
|
||||
#define BN_DEC_NUM 9
|
||||
#define TOBN(hi, lo) (lo), (hi)
|
||||
|
||||
#else
|
||||
#error "Must define either OPENSSL_32_BIT or OPENSSL_64_BIT"
|
||||
#endif
|
||||
|
||||
|
||||
#define STATIC_BIGNUM(x) \
|
||||
{ \
|
||||
(BN_ULONG *)(x), sizeof(x) / sizeof(BN_ULONG), \
|
||||
sizeof(x) / sizeof(BN_ULONG), 0, BN_FLG_STATIC_DATA \
|
||||
}
|
||||
|
||||
#if defined(BN_ULLONG)
|
||||
#define Lw(t) (((BN_ULONG)(t))&BN_MASK2)
|
||||
#define Hw(t) (((BN_ULONG)((t)>>BN_BITS2))&BN_MASK2)
|
||||
#endif
|
||||
|
||||
/* bn_set_words sets |bn| to the value encoded in the |num| words in |words|,
|
||||
* least significant word first. */
|
||||
int bn_set_words(BIGNUM *bn, const BN_ULONG *words, size_t num);
|
||||
|
||||
BN_ULONG bn_mul_add_words(BN_ULONG *rp, const BN_ULONG *ap, int num, BN_ULONG w);
|
||||
BN_ULONG bn_mul_words(BN_ULONG *rp, const BN_ULONG *ap, int num, BN_ULONG w);
|
||||
void bn_sqr_words(BN_ULONG *rp, const BN_ULONG *ap, int num);
|
||||
BN_ULONG bn_add_words(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,int num);
|
||||
BN_ULONG bn_sub_words(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,int num);
|
||||
|
||||
void bn_mul_comba4(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b);
|
||||
void bn_mul_comba8(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b);
|
||||
void bn_sqr_comba8(BN_ULONG *r, const BN_ULONG *a);
|
||||
void bn_sqr_comba4(BN_ULONG *r, const BN_ULONG *a);
|
||||
|
||||
/* bn_cmp_words returns a value less than, equal to or greater than zero if
|
||||
* the, length |n|, array |a| is less than, equal to or greater than |b|. */
|
||||
int bn_cmp_words(const BN_ULONG *a, const BN_ULONG *b, int n);
|
||||
|
||||
/* bn_cmp_words returns a value less than, equal to or greater than zero if the
|
||||
* array |a| is less than, equal to or greater than |b|. The arrays can be of
|
||||
* different lengths: |cl| gives the minimum of the two lengths and |dl| gives
|
||||
* the length of |a| minus the length of |b|. */
|
||||
int bn_cmp_part_words(const BN_ULONG *a, const BN_ULONG *b, int cl, int dl);
|
||||
|
||||
int bn_mul_mont(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
|
||||
const BN_ULONG *np, const BN_ULONG *n0, int num);
|
||||
|
||||
uint64_t bn_mont_n0(const BIGNUM *n);
|
||||
int bn_mod_exp_base_2_vartime(BIGNUM *r, unsigned p, const BIGNUM *n);
|
||||
|
||||
#if defined(OPENSSL_X86_64) && defined(_MSC_VER)
|
||||
#define BN_UMULT_LOHI(low, high, a, b) ((low) = _umul128((a), (b), &(high)))
|
||||
#endif
|
||||
|
||||
#if !defined(BN_ULLONG) && !defined(BN_UMULT_LOHI)
|
||||
#error "Either BN_ULLONG or BN_UMULT_LOHI must be defined on every platform."
|
||||
#endif
|
||||
|
||||
/* bn_mod_inverse_prime sets |out| to the modular inverse of |a| modulo |p|,
|
||||
* computed with Fermat's Little Theorem. It returns one on success and zero on
|
||||
* error. If |mont_p| is NULL, one will be computed temporarily. */
|
||||
int bn_mod_inverse_prime(BIGNUM *out, const BIGNUM *a, const BIGNUM *p,
|
||||
BN_CTX *ctx, const BN_MONT_CTX *mont_p);
|
||||
|
||||
/* bn_mod_inverse_secret_prime behaves like |bn_mod_inverse_prime| but uses
|
||||
* |BN_mod_exp_mont_consttime| instead of |BN_mod_exp_mont| in hopes of
|
||||
* protecting the exponent. */
|
||||
int bn_mod_inverse_secret_prime(BIGNUM *out, const BIGNUM *a, const BIGNUM *p,
|
||||
BN_CTX *ctx, const BN_MONT_CTX *mont_p);
|
||||
|
||||
|
||||
#if defined(__cplusplus)
|
||||
} /* extern C */
|
||||
#endif
|
||||
|
||||
#endif /* OPENSSL_HEADER_BN_INTERNAL_H */
|
||||
@@ -1,176 +0,0 @@
|
||||
/* ====================================================================
|
||||
* Copyright (c) 1998-2000 The OpenSSL Project. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. All advertising materials mentioning features or use of this
|
||||
* software must display the following acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
|
||||
*
|
||||
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
|
||||
* endorse or promote products derived from this software without
|
||||
* prior written permission. For written permission, please contact
|
||||
* openssl-core@openssl.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "OpenSSL"
|
||||
* nor may "OpenSSL" appear in their names without prior written
|
||||
* permission of the OpenSSL Project.
|
||||
*
|
||||
* 6. Redistributions of any form whatsoever must retain the following
|
||||
* acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit (http://www.openssl.org/)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
|
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ====================================================================
|
||||
*
|
||||
* This product includes cryptographic software written by Eric Young
|
||||
* (eay@cryptsoft.com). This product includes software written by Tim
|
||||
* Hudson (tjh@cryptsoft.com). */
|
||||
|
||||
#include <openssl/bn.h>
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
|
||||
/* least significant word */
|
||||
#define BN_lsw(n) (((n)->top == 0) ? (BN_ULONG) 0 : (n)->d[0])
|
||||
|
||||
/* Returns -2 for errors because both -1 and 0 are valid results. */
|
||||
int BN_kronecker(const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx) {
|
||||
int i;
|
||||
int ret = -2;
|
||||
BIGNUM *A, *B, *tmp;
|
||||
/* In 'tab', only odd-indexed entries are relevant:
|
||||
* For any odd BIGNUM n,
|
||||
* tab[BN_lsw(n) & 7]
|
||||
* is $(-1)^{(n^2-1)/8}$ (using TeX notation).
|
||||
* Note that the sign of n does not matter. */
|
||||
static const int tab[8] = {0, 1, 0, -1, 0, -1, 0, 1};
|
||||
|
||||
BN_CTX_start(ctx);
|
||||
A = BN_CTX_get(ctx);
|
||||
B = BN_CTX_get(ctx);
|
||||
if (B == NULL) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!BN_copy(A, a) ||
|
||||
!BN_copy(B, b)) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* Kronecker symbol, imlemented according to Henri Cohen,
|
||||
* "A Course in Computational Algebraic Number Theory"
|
||||
* (algorithm 1.4.10). */
|
||||
|
||||
/* Cohen's step 1: */
|
||||
|
||||
if (BN_is_zero(B)) {
|
||||
ret = BN_abs_is_word(A, 1);
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* Cohen's step 2: */
|
||||
|
||||
if (!BN_is_odd(A) && !BN_is_odd(B)) {
|
||||
ret = 0;
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* now B is non-zero */
|
||||
i = 0;
|
||||
while (!BN_is_bit_set(B, i)) {
|
||||
i++;
|
||||
}
|
||||
if (!BN_rshift(B, B, i)) {
|
||||
goto end;
|
||||
}
|
||||
if (i & 1) {
|
||||
/* i is odd */
|
||||
/* (thus B was even, thus A must be odd!) */
|
||||
|
||||
/* set 'ret' to $(-1)^{(A^2-1)/8}$ */
|
||||
ret = tab[BN_lsw(A) & 7];
|
||||
} else {
|
||||
/* i is even */
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
if (B->neg) {
|
||||
B->neg = 0;
|
||||
if (A->neg) {
|
||||
ret = -ret;
|
||||
}
|
||||
}
|
||||
|
||||
/* now B is positive and odd, so what remains to be done is to compute the
|
||||
* Jacobi symbol (A/B) and multiply it by 'ret' */
|
||||
|
||||
while (1) {
|
||||
/* Cohen's step 3: */
|
||||
|
||||
/* B is positive and odd */
|
||||
if (BN_is_zero(A)) {
|
||||
ret = BN_is_one(B) ? ret : 0;
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* now A is non-zero */
|
||||
i = 0;
|
||||
while (!BN_is_bit_set(A, i)) {
|
||||
i++;
|
||||
}
|
||||
if (!BN_rshift(A, A, i)) {
|
||||
ret = -2;
|
||||
goto end;
|
||||
}
|
||||
if (i & 1) {
|
||||
/* i is odd */
|
||||
/* multiply 'ret' by $(-1)^{(B^2-1)/8}$ */
|
||||
ret = ret * tab[BN_lsw(B) & 7];
|
||||
}
|
||||
|
||||
/* Cohen's step 4: */
|
||||
/* multiply 'ret' by $(-1)^{(A-1)(B-1)/4}$ */
|
||||
if ((A->neg ? ~BN_lsw(A) : BN_lsw(A)) & BN_lsw(B) & 2) {
|
||||
ret = -ret;
|
||||
}
|
||||
|
||||
/* (A, B) := (B mod |A|, |A|) */
|
||||
if (!BN_nnmod(B, B, A, ctx)) {
|
||||
ret = -2;
|
||||
goto end;
|
||||
}
|
||||
tmp = A;
|
||||
A = B;
|
||||
B = tmp;
|
||||
tmp->neg = 0;
|
||||
}
|
||||
|
||||
end:
|
||||
BN_CTX_end(ctx);
|
||||
return ret;
|
||||
}
|
||||
@@ -1,207 +0,0 @@
|
||||
/* Copyright 2016 Brian Smith.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
|
||||
|
||||
#include <openssl/bn.h>
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include "internal.h"
|
||||
#include "../internal.h"
|
||||
|
||||
|
||||
static uint64_t bn_neg_inv_mod_r_u64(uint64_t n);
|
||||
|
||||
OPENSSL_COMPILE_ASSERT(BN_MONT_CTX_N0_LIMBS == 1 || BN_MONT_CTX_N0_LIMBS == 2,
|
||||
BN_MONT_CTX_N0_LIMBS_VALUE_INVALID);
|
||||
OPENSSL_COMPILE_ASSERT(sizeof(uint64_t) ==
|
||||
BN_MONT_CTX_N0_LIMBS * sizeof(BN_ULONG),
|
||||
BN_MONT_CTX_N0_LIMBS_DOES_NOT_MATCH_UINT64_T);
|
||||
|
||||
/* LG_LITTLE_R is log_2(r). */
|
||||
#define LG_LITTLE_R (BN_MONT_CTX_N0_LIMBS * BN_BITS2)
|
||||
|
||||
uint64_t bn_mont_n0(const BIGNUM *n) {
|
||||
/* These conditions are checked by the caller, |BN_MONT_CTX_set|. */
|
||||
assert(!BN_is_zero(n));
|
||||
assert(!BN_is_negative(n));
|
||||
assert(BN_is_odd(n));
|
||||
|
||||
/* r == 2**(BN_MONT_CTX_N0_LIMBS * BN_BITS2) and LG_LITTLE_R == lg(r). This
|
||||
* ensures that we can do integer division by |r| by simply ignoring
|
||||
* |BN_MONT_CTX_N0_LIMBS| limbs. Similarly, we can calculate values modulo
|
||||
* |r| by just looking at the lowest |BN_MONT_CTX_N0_LIMBS| limbs. This is
|
||||
* what makes Montgomery multiplication efficient.
|
||||
*
|
||||
* As shown in Algorithm 1 of "Fast Prime Field Elliptic Curve Cryptography
|
||||
* with 256 Bit Primes" by Shay Gueron and Vlad Krasnov, in the loop of a
|
||||
* multi-limb Montgomery multiplication of |a * b (mod n)|, given the
|
||||
* unreduced product |t == a * b|, we repeatedly calculate:
|
||||
*
|
||||
* t1 := t % r |t1| is |t|'s lowest limb (see previous paragraph).
|
||||
* t2 := t1*n0*n
|
||||
* t3 := t + t2
|
||||
* t := t3 / r copy all limbs of |t3| except the lowest to |t|.
|
||||
*
|
||||
* In the last step, it would only make sense to ignore the lowest limb of
|
||||
* |t3| if it were zero. The middle steps ensure that this is the case:
|
||||
*
|
||||
* t3 == 0 (mod r)
|
||||
* t + t2 == 0 (mod r)
|
||||
* t + t1*n0*n == 0 (mod r)
|
||||
* t1*n0*n == -t (mod r)
|
||||
* t*n0*n == -t (mod r)
|
||||
* n0*n == -1 (mod r)
|
||||
* n0 == -1/n (mod r)
|
||||
*
|
||||
* Thus, in each iteration of the loop, we multiply by the constant factor
|
||||
* |n0|, the negative inverse of n (mod r). */
|
||||
|
||||
/* n_mod_r = n % r. As explained above, this is done by taking the lowest
|
||||
* |BN_MONT_CTX_N0_LIMBS| limbs of |n|. */
|
||||
uint64_t n_mod_r = n->d[0];
|
||||
#if BN_MONT_CTX_N0_LIMBS == 2
|
||||
if (n->top > 1) {
|
||||
n_mod_r |= (uint64_t)n->d[1] << BN_BITS2;
|
||||
}
|
||||
#endif
|
||||
|
||||
return bn_neg_inv_mod_r_u64(n_mod_r);
|
||||
}
|
||||
|
||||
/* bn_neg_inv_r_mod_n_u64 calculates the -1/n mod r; i.e. it calculates |v|
|
||||
* such that u*r - v*n == 1. |r| is the constant defined in |bn_mont_n0|. |n|
|
||||
* must be odd.
|
||||
*
|
||||
* This is derived from |xbinGCD| in Henry S. Warren, Jr.'s "Montgomery
|
||||
* Multiplication" (http://www.hackersdelight.org/MontgomeryMultiplication.pdf).
|
||||
* It is very similar to the MODULAR-INVERSE function in Stephen R. Dussé's and
|
||||
* Burton S. Kaliski Jr.'s "A Cryptographic Library for the Motorola DSP56000"
|
||||
* (http://link.springer.com/chapter/10.1007%2F3-540-46877-3_21).
|
||||
*
|
||||
* This is inspired by Joppe W. Bos's "Constant Time Modular Inversion"
|
||||
* (http://www.joppebos.com/files/CTInversion.pdf) so that the inversion is
|
||||
* constant-time with respect to |n|. We assume uint64_t additions,
|
||||
* subtractions, shifts, and bitwise operations are all constant time, which
|
||||
* may be a large leap of faith on 32-bit targets. We avoid division and
|
||||
* multiplication, which tend to be the most problematic in terms of timing
|
||||
* leaks.
|
||||
*
|
||||
* Most GCD implementations return values such that |u*r + v*n == 1|, so the
|
||||
* caller would have to negate the resultant |v| for the purpose of Montgomery
|
||||
* multiplication. This implementation does the negation implicitly by doing
|
||||
* the computations as a difference instead of a sum. */
|
||||
static uint64_t bn_neg_inv_mod_r_u64(uint64_t n) {
|
||||
assert(n % 2 == 1);
|
||||
|
||||
/* alpha == 2**(lg r - 1) == r / 2. */
|
||||
static const uint64_t alpha = UINT64_C(1) << (LG_LITTLE_R - 1);
|
||||
|
||||
const uint64_t beta = n;
|
||||
|
||||
uint64_t u = 1;
|
||||
uint64_t v = 0;
|
||||
|
||||
/* The invariant maintained from here on is:
|
||||
* 2**(lg r - i) == u*2*alpha - v*beta. */
|
||||
for (size_t i = 0; i < LG_LITTLE_R; ++i) {
|
||||
#if BN_BITS2 == 64 && defined(BN_ULLONG)
|
||||
assert((BN_ULLONG)(1) << (LG_LITTLE_R - i) ==
|
||||
((BN_ULLONG)u * 2 * alpha) - ((BN_ULLONG)v * beta));
|
||||
#endif
|
||||
|
||||
/* Delete a common factor of 2 in u and v if |u| is even. Otherwise, set
|
||||
* |u = (u + beta) / 2| and |v = (v / 2) + alpha|. */
|
||||
|
||||
uint64_t u_is_odd = UINT64_C(0) - (u & 1); /* Either 0xff..ff or 0. */
|
||||
|
||||
/* The addition can overflow, so use Dietz's method for it.
|
||||
*
|
||||
* Dietz calculates (x+y)/2 by (x⊕y)>>1 + x&y. This is valid for all
|
||||
* (unsigned) x and y, even when x+y overflows. Evidence for 32-bit values
|
||||
* (embedded in 64 bits to so that overflow can be ignored):
|
||||
*
|
||||
* (declare-fun x () (_ BitVec 64))
|
||||
* (declare-fun y () (_ BitVec 64))
|
||||
* (assert (let (
|
||||
* (one (_ bv1 64))
|
||||
* (thirtyTwo (_ bv32 64)))
|
||||
* (and
|
||||
* (bvult x (bvshl one thirtyTwo))
|
||||
* (bvult y (bvshl one thirtyTwo))
|
||||
* (not (=
|
||||
* (bvadd (bvlshr (bvxor x y) one) (bvand x y))
|
||||
* (bvlshr (bvadd x y) one)))
|
||||
* )))
|
||||
* (check-sat) */
|
||||
uint64_t beta_if_u_is_odd = beta & u_is_odd; /* Either |beta| or 0. */
|
||||
u = ((u ^ beta_if_u_is_odd) >> 1) + (u & beta_if_u_is_odd);
|
||||
|
||||
uint64_t alpha_if_u_is_odd = alpha & u_is_odd; /* Either |alpha| or 0. */
|
||||
v = (v >> 1) + alpha_if_u_is_odd;
|
||||
}
|
||||
|
||||
/* The invariant now shows that u*r - v*n == 1 since r == 2 * alpha. */
|
||||
#if BN_BITS2 == 64 && defined(BN_ULLONG)
|
||||
assert(1 == ((BN_ULLONG)u * 2 * alpha) - ((BN_ULLONG)v * beta));
|
||||
#endif
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
/* bn_mod_exp_base_2_vartime calculates r = 2**p (mod n). |p| must be larger
|
||||
* than log_2(n); i.e. 2**p must be larger than |n|. |n| must be positive and
|
||||
* odd. */
|
||||
int bn_mod_exp_base_2_vartime(BIGNUM *r, unsigned p, const BIGNUM *n) {
|
||||
assert(!BN_is_zero(n));
|
||||
assert(!BN_is_negative(n));
|
||||
assert(BN_is_odd(n));
|
||||
|
||||
BN_zero(r);
|
||||
|
||||
unsigned n_bits = BN_num_bits(n);
|
||||
assert(n_bits != 0);
|
||||
if (n_bits == 1) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Set |r| to the smallest power of two larger than |n|. */
|
||||
assert(p > n_bits);
|
||||
if (!BN_set_bit(r, n_bits)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Unconditionally reduce |r|. */
|
||||
assert(BN_cmp(r, n) > 0);
|
||||
if (!BN_usub(r, r, n)) {
|
||||
return 0;
|
||||
}
|
||||
assert(BN_cmp(r, n) < 0);
|
||||
|
||||
for (unsigned i = n_bits; i < p; ++i) {
|
||||
/* This is like |BN_mod_lshift1_quick| except using |BN_usub|.
|
||||
*
|
||||
* TODO: Replace this with the use of a constant-time variant of
|
||||
* |BN_mod_lshift1_quick|. */
|
||||
if (!BN_lshift1(r, r)) {
|
||||
return 0;
|
||||
}
|
||||
if (BN_cmp(r, n) >= 0) {
|
||||
if (!BN_usub(r, r, n)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -1,343 +0,0 @@
|
||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young (eay@cryptsoft.com).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young (eay@cryptsoft.com)"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.]
|
||||
*/
|
||||
/* ====================================================================
|
||||
* Copyright (c) 1998-2001 The OpenSSL Project. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. All advertising materials mentioning features or use of this
|
||||
* software must display the following acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
|
||||
*
|
||||
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
|
||||
* endorse or promote products derived from this software without
|
||||
* prior written permission. For written permission, please contact
|
||||
* openssl-core@openssl.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "OpenSSL"
|
||||
* nor may "OpenSSL" appear in their names without prior written
|
||||
* permission of the OpenSSL Project.
|
||||
*
|
||||
* 6. Redistributions of any form whatsoever must retain the following
|
||||
* acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit (http://www.openssl.org/)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
|
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ====================================================================
|
||||
*
|
||||
* This product includes cryptographic software written by Eric Young
|
||||
* (eay@cryptsoft.com). This product includes software written by Tim
|
||||
* Hudson (tjh@cryptsoft.com). */
|
||||
|
||||
#include <openssl/bn.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.h>
|
||||
#include <openssl/rand.h>
|
||||
#include <openssl/sha.h>
|
||||
|
||||
#include "../internal.h"
|
||||
|
||||
|
||||
int BN_rand(BIGNUM *rnd, int bits, int top, int bottom) {
|
||||
uint8_t *buf = NULL;
|
||||
int ret = 0, bit, bytes, mask;
|
||||
|
||||
if (rnd == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (top != BN_RAND_TOP_ANY && top != BN_RAND_TOP_ONE &&
|
||||
top != BN_RAND_TOP_TWO) {
|
||||
OPENSSL_PUT_ERROR(BN, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (bottom != BN_RAND_BOTTOM_ANY && bottom != BN_RAND_BOTTOM_ODD) {
|
||||
OPENSSL_PUT_ERROR(BN, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (bits == 0) {
|
||||
BN_zero(rnd);
|
||||
return 1;
|
||||
}
|
||||
|
||||
bytes = (bits + 7) / 8;
|
||||
bit = (bits - 1) % 8;
|
||||
mask = 0xff << (bit + 1);
|
||||
|
||||
buf = OPENSSL_malloc(bytes);
|
||||
if (buf == NULL) {
|
||||
OPENSSL_PUT_ERROR(BN, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Make a random number and set the top and bottom bits. */
|
||||
if (!RAND_bytes(buf, bytes)) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (top != BN_RAND_TOP_ANY) {
|
||||
if (top == BN_RAND_TOP_TWO && bits > 1) {
|
||||
if (bit == 0) {
|
||||
buf[0] = 1;
|
||||
buf[1] |= 0x80;
|
||||
} else {
|
||||
buf[0] |= (3 << (bit - 1));
|
||||
}
|
||||
} else {
|
||||
buf[0] |= (1 << bit);
|
||||
}
|
||||
}
|
||||
|
||||
buf[0] &= ~mask;
|
||||
|
||||
/* Set the bottom bit if requested, */
|
||||
if (bottom == BN_RAND_BOTTOM_ODD) {
|
||||
buf[bytes - 1] |= 1;
|
||||
}
|
||||
|
||||
if (!BN_bin2bn(buf, bytes, rnd)) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = 1;
|
||||
|
||||
err:
|
||||
if (buf != NULL) {
|
||||
OPENSSL_cleanse(buf, bytes);
|
||||
OPENSSL_free(buf);
|
||||
}
|
||||
return (ret);
|
||||
}
|
||||
|
||||
int BN_pseudo_rand(BIGNUM *rnd, int bits, int top, int bottom) {
|
||||
return BN_rand(rnd, bits, top, bottom);
|
||||
}
|
||||
|
||||
int BN_rand_range_ex(BIGNUM *r, BN_ULONG min_inclusive,
|
||||
const BIGNUM *max_exclusive) {
|
||||
unsigned n;
|
||||
unsigned count = 100;
|
||||
|
||||
if (BN_cmp_word(max_exclusive, min_inclusive) <= 0) {
|
||||
OPENSSL_PUT_ERROR(BN, BN_R_INVALID_RANGE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
n = BN_num_bits(max_exclusive); /* n > 0 */
|
||||
|
||||
/* BN_is_bit_set(range, n - 1) always holds */
|
||||
if (n == 1) {
|
||||
BN_zero(r);
|
||||
return 1;
|
||||
}
|
||||
|
||||
do {
|
||||
if (!--count) {
|
||||
OPENSSL_PUT_ERROR(BN, BN_R_TOO_MANY_ITERATIONS);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!BN_is_bit_set(max_exclusive, n - 2) &&
|
||||
!BN_is_bit_set(max_exclusive, n - 3)) {
|
||||
/* range = 100..._2, so 3*range (= 11..._2) is exactly one bit longer
|
||||
* than range. This is a common scenario when generating a random value
|
||||
* modulo an RSA public modulus, e.g. for RSA base blinding. */
|
||||
if (!BN_rand(r, n + 1, BN_RAND_TOP_ANY, BN_RAND_BOTTOM_ANY)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* If r < 3*range, use r := r MOD range (which is either r, r - range, or
|
||||
* r - 2*range). Otherwise, iterate again. Since 3*range = 11..._2, each
|
||||
* iteration succeeds with probability >= .75. */
|
||||
if (BN_cmp(r, max_exclusive) >= 0) {
|
||||
if (!BN_sub(r, r, max_exclusive)) {
|
||||
return 0;
|
||||
}
|
||||
if (BN_cmp(r, max_exclusive) >= 0) {
|
||||
if (!BN_sub(r, r, max_exclusive)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* range = 11..._2 or range = 101..._2 */
|
||||
if (!BN_rand(r, n, BN_RAND_TOP_ANY, BN_RAND_BOTTOM_ANY)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
} while (BN_cmp_word(r, min_inclusive) < 0 ||
|
||||
BN_cmp(r, max_exclusive) >= 0);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int BN_rand_range(BIGNUM *r, const BIGNUM *range) {
|
||||
return BN_rand_range_ex(r, 0, range);
|
||||
}
|
||||
|
||||
int BN_pseudo_rand_range(BIGNUM *r, const BIGNUM *range) {
|
||||
return BN_rand_range(r, range);
|
||||
}
|
||||
|
||||
int BN_generate_dsa_nonce(BIGNUM *out, const BIGNUM *range, const BIGNUM *priv,
|
||||
const uint8_t *message, size_t message_len,
|
||||
BN_CTX *ctx) {
|
||||
SHA512_CTX sha;
|
||||
/* We use 512 bits of random data per iteration to
|
||||
* ensure that we have at least |range| bits of randomness. */
|
||||
uint8_t random_bytes[64];
|
||||
uint8_t digest[SHA512_DIGEST_LENGTH];
|
||||
size_t done, todo, attempt;
|
||||
const unsigned num_k_bytes = BN_num_bytes(range);
|
||||
const unsigned bits_to_mask = (8 - (BN_num_bits(range) % 8)) % 8;
|
||||
uint8_t private_bytes[96];
|
||||
uint8_t *k_bytes = NULL;
|
||||
int ret = 0;
|
||||
|
||||
if (out == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (BN_is_zero(range)) {
|
||||
OPENSSL_PUT_ERROR(BN, BN_R_DIV_BY_ZERO);
|
||||
goto err;
|
||||
}
|
||||
|
||||
k_bytes = OPENSSL_malloc(num_k_bytes);
|
||||
if (!k_bytes) {
|
||||
OPENSSL_PUT_ERROR(BN, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* We copy |priv| into a local buffer to avoid furthur exposing its
|
||||
* length. */
|
||||
todo = sizeof(priv->d[0]) * priv->top;
|
||||
if (todo > sizeof(private_bytes)) {
|
||||
/* No reasonable DSA or ECDSA key should have a private key
|
||||
* this large and we don't handle this case in order to avoid
|
||||
* leaking the length of the private key. */
|
||||
OPENSSL_PUT_ERROR(BN, BN_R_PRIVATE_KEY_TOO_LARGE);
|
||||
goto err;
|
||||
}
|
||||
OPENSSL_memcpy(private_bytes, priv->d, todo);
|
||||
OPENSSL_memset(private_bytes + todo, 0, sizeof(private_bytes) - todo);
|
||||
|
||||
for (attempt = 0;; attempt++) {
|
||||
for (done = 0; done < num_k_bytes;) {
|
||||
if (!RAND_bytes(random_bytes, sizeof(random_bytes))) {
|
||||
goto err;
|
||||
}
|
||||
SHA512_Init(&sha);
|
||||
SHA512_Update(&sha, &attempt, sizeof(attempt));
|
||||
SHA512_Update(&sha, &done, sizeof(done));
|
||||
SHA512_Update(&sha, private_bytes, sizeof(private_bytes));
|
||||
SHA512_Update(&sha, message, message_len);
|
||||
SHA512_Update(&sha, random_bytes, sizeof(random_bytes));
|
||||
SHA512_Final(digest, &sha);
|
||||
|
||||
todo = num_k_bytes - done;
|
||||
if (todo > SHA512_DIGEST_LENGTH) {
|
||||
todo = SHA512_DIGEST_LENGTH;
|
||||
}
|
||||
OPENSSL_memcpy(k_bytes + done, digest, todo);
|
||||
done += todo;
|
||||
}
|
||||
|
||||
k_bytes[0] &= 0xff >> bits_to_mask;
|
||||
|
||||
if (!BN_bin2bn(k_bytes, num_k_bytes, out)) {
|
||||
goto err;
|
||||
}
|
||||
if (BN_cmp(out, range) < 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ret = 1;
|
||||
|
||||
err:
|
||||
OPENSSL_free(k_bytes);
|
||||
return ret;
|
||||
}
|
||||
@@ -1,506 +0,0 @@
|
||||
/* Written by Lenka Fibikova <fibikova@exp-math.uni-essen.de>
|
||||
* and Bodo Moeller for the OpenSSL project. */
|
||||
/* ====================================================================
|
||||
* Copyright (c) 1998-2000 The OpenSSL Project. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. All advertising materials mentioning features or use of this
|
||||
* software must display the following acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
|
||||
*
|
||||
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
|
||||
* endorse or promote products derived from this software without
|
||||
* prior written permission. For written permission, please contact
|
||||
* openssl-core@openssl.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "OpenSSL"
|
||||
* nor may "OpenSSL" appear in their names without prior written
|
||||
* permission of the OpenSSL Project.
|
||||
*
|
||||
* 6. Redistributions of any form whatsoever must retain the following
|
||||
* acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit (http://www.openssl.org/)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
|
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ====================================================================
|
||||
*
|
||||
* This product includes cryptographic software written by Eric Young
|
||||
* (eay@cryptsoft.com). This product includes software written by Tim
|
||||
* Hudson (tjh@cryptsoft.com). */
|
||||
|
||||
#include <openssl/bn.h>
|
||||
|
||||
#include <openssl/err.h>
|
||||
|
||||
|
||||
BIGNUM *BN_mod_sqrt(BIGNUM *in, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx) {
|
||||
/* Compute a square root of |a| mod |p| using the Tonelli/Shanks algorithm
|
||||
* (cf. Henri Cohen, "A Course in Algebraic Computational Number Theory",
|
||||
* algorithm 1.5.1). |p| is assumed to be a prime. */
|
||||
|
||||
BIGNUM *ret = in;
|
||||
int err = 1;
|
||||
int r;
|
||||
BIGNUM *A, *b, *q, *t, *x, *y;
|
||||
int e, i, j;
|
||||
|
||||
if (!BN_is_odd(p) || BN_abs_is_word(p, 1)) {
|
||||
if (BN_abs_is_word(p, 2)) {
|
||||
if (ret == NULL) {
|
||||
ret = BN_new();
|
||||
}
|
||||
if (ret == NULL) {
|
||||
goto end;
|
||||
}
|
||||
if (!BN_set_word(ret, BN_is_bit_set(a, 0))) {
|
||||
if (ret != in) {
|
||||
BN_free(ret);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
OPENSSL_PUT_ERROR(BN, BN_R_P_IS_NOT_PRIME);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
if (BN_is_zero(a) || BN_is_one(a)) {
|
||||
if (ret == NULL) {
|
||||
ret = BN_new();
|
||||
}
|
||||
if (ret == NULL) {
|
||||
goto end;
|
||||
}
|
||||
if (!BN_set_word(ret, BN_is_one(a))) {
|
||||
if (ret != in) {
|
||||
BN_free(ret);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
BN_CTX_start(ctx);
|
||||
A = BN_CTX_get(ctx);
|
||||
b = BN_CTX_get(ctx);
|
||||
q = BN_CTX_get(ctx);
|
||||
t = BN_CTX_get(ctx);
|
||||
x = BN_CTX_get(ctx);
|
||||
y = BN_CTX_get(ctx);
|
||||
if (y == NULL) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (ret == NULL) {
|
||||
ret = BN_new();
|
||||
}
|
||||
if (ret == NULL) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* A = a mod p */
|
||||
if (!BN_nnmod(A, a, p, ctx)) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* now write |p| - 1 as 2^e*q where q is odd */
|
||||
e = 1;
|
||||
while (!BN_is_bit_set(p, e)) {
|
||||
e++;
|
||||
}
|
||||
/* we'll set q later (if needed) */
|
||||
|
||||
if (e == 1) {
|
||||
/* The easy case: (|p|-1)/2 is odd, so 2 has an inverse
|
||||
* modulo (|p|-1)/2, and square roots can be computed
|
||||
* directly by modular exponentiation.
|
||||
* We have
|
||||
* 2 * (|p|+1)/4 == 1 (mod (|p|-1)/2),
|
||||
* so we can use exponent (|p|+1)/4, i.e. (|p|-3)/4 + 1.
|
||||
*/
|
||||
if (!BN_rshift(q, p, 2)) {
|
||||
goto end;
|
||||
}
|
||||
q->neg = 0;
|
||||
if (!BN_add_word(q, 1) ||
|
||||
!BN_mod_exp(ret, A, q, p, ctx)) {
|
||||
goto end;
|
||||
}
|
||||
err = 0;
|
||||
goto vrfy;
|
||||
}
|
||||
|
||||
if (e == 2) {
|
||||
/* |p| == 5 (mod 8)
|
||||
*
|
||||
* In this case 2 is always a non-square since
|
||||
* Legendre(2,p) = (-1)^((p^2-1)/8) for any odd prime.
|
||||
* So if a really is a square, then 2*a is a non-square.
|
||||
* Thus for
|
||||
* b := (2*a)^((|p|-5)/8),
|
||||
* i := (2*a)*b^2
|
||||
* we have
|
||||
* i^2 = (2*a)^((1 + (|p|-5)/4)*2)
|
||||
* = (2*a)^((p-1)/2)
|
||||
* = -1;
|
||||
* so if we set
|
||||
* x := a*b*(i-1),
|
||||
* then
|
||||
* x^2 = a^2 * b^2 * (i^2 - 2*i + 1)
|
||||
* = a^2 * b^2 * (-2*i)
|
||||
* = a*(-i)*(2*a*b^2)
|
||||
* = a*(-i)*i
|
||||
* = a.
|
||||
*
|
||||
* (This is due to A.O.L. Atkin,
|
||||
* <URL:
|
||||
*http://listserv.nodak.edu/scripts/wa.exe?A2=ind9211&L=nmbrthry&O=T&P=562>,
|
||||
* November 1992.)
|
||||
*/
|
||||
|
||||
/* t := 2*a */
|
||||
if (!BN_mod_lshift1_quick(t, A, p)) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* b := (2*a)^((|p|-5)/8) */
|
||||
if (!BN_rshift(q, p, 3)) {
|
||||
goto end;
|
||||
}
|
||||
q->neg = 0;
|
||||
if (!BN_mod_exp(b, t, q, p, ctx)) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* y := b^2 */
|
||||
if (!BN_mod_sqr(y, b, p, ctx)) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* t := (2*a)*b^2 - 1*/
|
||||
if (!BN_mod_mul(t, t, y, p, ctx) ||
|
||||
!BN_sub_word(t, 1)) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* x = a*b*t */
|
||||
if (!BN_mod_mul(x, A, b, p, ctx) ||
|
||||
!BN_mod_mul(x, x, t, p, ctx)) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!BN_copy(ret, x)) {
|
||||
goto end;
|
||||
}
|
||||
err = 0;
|
||||
goto vrfy;
|
||||
}
|
||||
|
||||
/* e > 2, so we really have to use the Tonelli/Shanks algorithm.
|
||||
* First, find some y that is not a square. */
|
||||
if (!BN_copy(q, p)) {
|
||||
goto end; /* use 'q' as temp */
|
||||
}
|
||||
q->neg = 0;
|
||||
i = 2;
|
||||
do {
|
||||
/* For efficiency, try small numbers first;
|
||||
* if this fails, try random numbers.
|
||||
*/
|
||||
if (i < 22) {
|
||||
if (!BN_set_word(y, i)) {
|
||||
goto end;
|
||||
}
|
||||
} else {
|
||||
if (!BN_pseudo_rand(y, BN_num_bits(p), 0, 0)) {
|
||||
goto end;
|
||||
}
|
||||
if (BN_ucmp(y, p) >= 0) {
|
||||
if (!(p->neg ? BN_add : BN_sub)(y, y, p)) {
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
/* now 0 <= y < |p| */
|
||||
if (BN_is_zero(y)) {
|
||||
if (!BN_set_word(y, i)) {
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
r = BN_kronecker(y, q, ctx); /* here 'q' is |p| */
|
||||
if (r < -1) {
|
||||
goto end;
|
||||
}
|
||||
if (r == 0) {
|
||||
/* m divides p */
|
||||
OPENSSL_PUT_ERROR(BN, BN_R_P_IS_NOT_PRIME);
|
||||
goto end;
|
||||
}
|
||||
} while (r == 1 && ++i < 82);
|
||||
|
||||
if (r != -1) {
|
||||
/* Many rounds and still no non-square -- this is more likely
|
||||
* a bug than just bad luck.
|
||||
* Even if p is not prime, we should have found some y
|
||||
* such that r == -1.
|
||||
*/
|
||||
OPENSSL_PUT_ERROR(BN, BN_R_TOO_MANY_ITERATIONS);
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* Here's our actual 'q': */
|
||||
if (!BN_rshift(q, q, e)) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* Now that we have some non-square, we can find an element
|
||||
* of order 2^e by computing its q'th power. */
|
||||
if (!BN_mod_exp(y, y, q, p, ctx)) {
|
||||
goto end;
|
||||
}
|
||||
if (BN_is_one(y)) {
|
||||
OPENSSL_PUT_ERROR(BN, BN_R_P_IS_NOT_PRIME);
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* Now we know that (if p is indeed prime) there is an integer
|
||||
* k, 0 <= k < 2^e, such that
|
||||
*
|
||||
* a^q * y^k == 1 (mod p).
|
||||
*
|
||||
* As a^q is a square and y is not, k must be even.
|
||||
* q+1 is even, too, so there is an element
|
||||
*
|
||||
* X := a^((q+1)/2) * y^(k/2),
|
||||
*
|
||||
* and it satisfies
|
||||
*
|
||||
* X^2 = a^q * a * y^k
|
||||
* = a,
|
||||
*
|
||||
* so it is the square root that we are looking for.
|
||||
*/
|
||||
|
||||
/* t := (q-1)/2 (note that q is odd) */
|
||||
if (!BN_rshift1(t, q)) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* x := a^((q-1)/2) */
|
||||
if (BN_is_zero(t)) /* special case: p = 2^e + 1 */
|
||||
{
|
||||
if (!BN_nnmod(t, A, p, ctx)) {
|
||||
goto end;
|
||||
}
|
||||
if (BN_is_zero(t)) {
|
||||
/* special case: a == 0 (mod p) */
|
||||
BN_zero(ret);
|
||||
err = 0;
|
||||
goto end;
|
||||
} else if (!BN_one(x)) {
|
||||
goto end;
|
||||
}
|
||||
} else {
|
||||
if (!BN_mod_exp(x, A, t, p, ctx)) {
|
||||
goto end;
|
||||
}
|
||||
if (BN_is_zero(x)) {
|
||||
/* special case: a == 0 (mod p) */
|
||||
BN_zero(ret);
|
||||
err = 0;
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
/* b := a*x^2 (= a^q) */
|
||||
if (!BN_mod_sqr(b, x, p, ctx) ||
|
||||
!BN_mod_mul(b, b, A, p, ctx)) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* x := a*x (= a^((q+1)/2)) */
|
||||
if (!BN_mod_mul(x, x, A, p, ctx)) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
while (1) {
|
||||
/* Now b is a^q * y^k for some even k (0 <= k < 2^E
|
||||
* where E refers to the original value of e, which we
|
||||
* don't keep in a variable), and x is a^((q+1)/2) * y^(k/2).
|
||||
*
|
||||
* We have a*b = x^2,
|
||||
* y^2^(e-1) = -1,
|
||||
* b^2^(e-1) = 1.
|
||||
*/
|
||||
|
||||
if (BN_is_one(b)) {
|
||||
if (!BN_copy(ret, x)) {
|
||||
goto end;
|
||||
}
|
||||
err = 0;
|
||||
goto vrfy;
|
||||
}
|
||||
|
||||
|
||||
/* find smallest i such that b^(2^i) = 1 */
|
||||
i = 1;
|
||||
if (!BN_mod_sqr(t, b, p, ctx)) {
|
||||
goto end;
|
||||
}
|
||||
while (!BN_is_one(t)) {
|
||||
i++;
|
||||
if (i == e) {
|
||||
OPENSSL_PUT_ERROR(BN, BN_R_NOT_A_SQUARE);
|
||||
goto end;
|
||||
}
|
||||
if (!BN_mod_mul(t, t, t, p, ctx)) {
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* t := y^2^(e - i - 1) */
|
||||
if (!BN_copy(t, y)) {
|
||||
goto end;
|
||||
}
|
||||
for (j = e - i - 1; j > 0; j--) {
|
||||
if (!BN_mod_sqr(t, t, p, ctx)) {
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
if (!BN_mod_mul(y, t, t, p, ctx) ||
|
||||
!BN_mod_mul(x, x, t, p, ctx) ||
|
||||
!BN_mod_mul(b, b, y, p, ctx)) {
|
||||
goto end;
|
||||
}
|
||||
e = i;
|
||||
}
|
||||
|
||||
vrfy:
|
||||
if (!err) {
|
||||
/* verify the result -- the input might have been not a square
|
||||
* (test added in 0.9.8) */
|
||||
|
||||
if (!BN_mod_sqr(x, ret, p, ctx)) {
|
||||
err = 1;
|
||||
}
|
||||
|
||||
if (!err && 0 != BN_cmp(x, A)) {
|
||||
OPENSSL_PUT_ERROR(BN, BN_R_NOT_A_SQUARE);
|
||||
err = 1;
|
||||
}
|
||||
}
|
||||
|
||||
end:
|
||||
if (err) {
|
||||
if (ret != in) {
|
||||
BN_clear_free(ret);
|
||||
}
|
||||
ret = NULL;
|
||||
}
|
||||
BN_CTX_end(ctx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int BN_sqrt(BIGNUM *out_sqrt, const BIGNUM *in, BN_CTX *ctx) {
|
||||
BIGNUM *estimate, *tmp, *delta, *last_delta, *tmp2;
|
||||
int ok = 0, last_delta_valid = 0;
|
||||
|
||||
if (in->neg) {
|
||||
OPENSSL_PUT_ERROR(BN, BN_R_NEGATIVE_NUMBER);
|
||||
return 0;
|
||||
}
|
||||
if (BN_is_zero(in)) {
|
||||
BN_zero(out_sqrt);
|
||||
return 1;
|
||||
}
|
||||
|
||||
BN_CTX_start(ctx);
|
||||
if (out_sqrt == in) {
|
||||
estimate = BN_CTX_get(ctx);
|
||||
} else {
|
||||
estimate = out_sqrt;
|
||||
}
|
||||
tmp = BN_CTX_get(ctx);
|
||||
last_delta = BN_CTX_get(ctx);
|
||||
delta = BN_CTX_get(ctx);
|
||||
if (estimate == NULL || tmp == NULL || last_delta == NULL || delta == NULL) {
|
||||
OPENSSL_PUT_ERROR(BN, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* We estimate that the square root of an n-bit number is 2^{n/2}. */
|
||||
if (!BN_lshift(estimate, BN_value_one(), BN_num_bits(in)/2)) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* This is Newton's method for finding a root of the equation |estimate|^2 -
|
||||
* |in| = 0. */
|
||||
for (;;) {
|
||||
/* |estimate| = 1/2 * (|estimate| + |in|/|estimate|) */
|
||||
if (!BN_div(tmp, NULL, in, estimate, ctx) ||
|
||||
!BN_add(tmp, tmp, estimate) ||
|
||||
!BN_rshift1(estimate, tmp) ||
|
||||
/* |tmp| = |estimate|^2 */
|
||||
!BN_sqr(tmp, estimate, ctx) ||
|
||||
/* |delta| = |in| - |tmp| */
|
||||
!BN_sub(delta, in, tmp)) {
|
||||
OPENSSL_PUT_ERROR(BN, ERR_R_BN_LIB);
|
||||
goto err;
|
||||
}
|
||||
|
||||
delta->neg = 0;
|
||||
/* The difference between |in| and |estimate| squared is required to always
|
||||
* decrease. This ensures that the loop always terminates, but I don't have
|
||||
* a proof that it always finds the square root for a given square. */
|
||||
if (last_delta_valid && BN_cmp(delta, last_delta) >= 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
last_delta_valid = 1;
|
||||
|
||||
tmp2 = last_delta;
|
||||
last_delta = delta;
|
||||
delta = tmp2;
|
||||
}
|
||||
|
||||
if (BN_cmp(tmp, in) != 0) {
|
||||
OPENSSL_PUT_ERROR(BN, BN_R_NOT_A_SQUARE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
ok = 1;
|
||||
|
||||
err:
|
||||
if (ok && out_sqrt == in && !BN_copy(out_sqrt, estimate)) {
|
||||
ok = 0;
|
||||
}
|
||||
BN_CTX_end(ctx);
|
||||
return ok;
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
include_directories(../../include)
|
||||
|
||||
add_library(
|
||||
bn_extra
|
||||
|
||||
OBJECT
|
||||
|
||||
bn_asn1.c
|
||||
convert.c
|
||||
)
|
||||
@@ -31,7 +31,7 @@ int BN_parse_asn1_unsigned(CBS *cbs, BIGNUM *ret) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* INTEGERs must be minimal. */
|
||||
// INTEGERs must be minimal.
|
||||
if (CBS_data(&child)[0] == 0x00 &&
|
||||
CBS_len(&child) > 1 &&
|
||||
!(CBS_data(&child)[1] & 0x80)) {
|
||||
@@ -50,16 +50,16 @@ int BN_parse_asn1_unsigned_buggy(CBS *cbs, BIGNUM *ret) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This function intentionally does not reject negative numbers or non-minimal
|
||||
* encodings. Estonian IDs issued between September 2014 to September 2015 are
|
||||
* broken. See https://crbug.com/532048 and https://crbug.com/534766.
|
||||
*
|
||||
* TODO(davidben): Remove this code and callers in March 2016. */
|
||||
// This function intentionally does not reject negative numbers or non-minimal
|
||||
// encodings. Estonian IDs issued between September 2014 to September 2015 are
|
||||
// broken. See https://crbug.com/532048 and https://crbug.com/534766.
|
||||
//
|
||||
// TODO(davidben): Remove this code and callers in March 2016.
|
||||
return BN_bin2bn(CBS_data(&child), CBS_len(&child), ret) != NULL;
|
||||
}
|
||||
|
||||
int BN_marshal_asn1(CBB *cbb, const BIGNUM *bn) {
|
||||
/* Negative numbers are unsupported. */
|
||||
// Negative numbers are unsupported.
|
||||
if (BN_is_negative(bn)) {
|
||||
OPENSSL_PUT_ERROR(BN, BN_R_NEGATIVE_NUMBER);
|
||||
return 0;
|
||||
@@ -67,8 +67,8 @@ int BN_marshal_asn1(CBB *cbb, const BIGNUM *bn) {
|
||||
|
||||
CBB child;
|
||||
if (!CBB_add_asn1(cbb, &child, CBS_ASN1_INTEGER) ||
|
||||
/* The number must be padded with a leading zero if the high bit would
|
||||
* otherwise be set or if |bn| is zero. */
|
||||
// The number must be padded with a leading zero if the high bit would
|
||||
// otherwise be set or if |bn| is zero.
|
||||
(BN_num_bits(bn) % 8 == 0 && !CBB_add_u8(&child, 0x00)) ||
|
||||
!BN_bn2cbb_padded(&child, BN_num_bytes(bn), bn) ||
|
||||
!CBB_flush(cbb)) {
|
||||
@@ -0,0 +1,465 @@
|
||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young (eay@cryptsoft.com).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young (eay@cryptsoft.com)"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.] */
|
||||
|
||||
#include <openssl/bn.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <openssl/bio.h>
|
||||
#include <openssl/bytestring.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.h>
|
||||
|
||||
#include "../fipsmodule/bn/internal.h"
|
||||
|
||||
|
||||
int BN_bn2cbb_padded(CBB *out, size_t len, const BIGNUM *in) {
|
||||
uint8_t *ptr;
|
||||
return CBB_add_space(out, &ptr, len) && BN_bn2bin_padded(ptr, len, in);
|
||||
}
|
||||
|
||||
static const char hextable[] = "0123456789abcdef";
|
||||
|
||||
char *BN_bn2hex(const BIGNUM *bn) {
|
||||
char *buf = OPENSSL_malloc(1 /* leading '-' */ + 1 /* zero is non-empty */ +
|
||||
bn->top * BN_BYTES * 2 + 1 /* trailing NUL */);
|
||||
if (buf == NULL) {
|
||||
OPENSSL_PUT_ERROR(BN, ERR_R_MALLOC_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *p = buf;
|
||||
if (bn->neg) {
|
||||
*(p++) = '-';
|
||||
}
|
||||
|
||||
if (BN_is_zero(bn)) {
|
||||
*(p++) = '0';
|
||||
}
|
||||
|
||||
int z = 0;
|
||||
for (int i = bn->top - 1; i >= 0; i--) {
|
||||
for (int j = BN_BITS2 - 8; j >= 0; j -= 8) {
|
||||
// strip leading zeros
|
||||
int v = ((int)(bn->d[i] >> (long)j)) & 0xff;
|
||||
if (z || v != 0) {
|
||||
*(p++) = hextable[v >> 4];
|
||||
*(p++) = hextable[v & 0x0f];
|
||||
z = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
*p = '\0';
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
// decode_hex decodes |in_len| bytes of hex data from |in| and updates |bn|.
|
||||
static int decode_hex(BIGNUM *bn, const char *in, int in_len) {
|
||||
if (in_len > INT_MAX/4) {
|
||||
OPENSSL_PUT_ERROR(BN, BN_R_BIGNUM_TOO_LONG);
|
||||
return 0;
|
||||
}
|
||||
// |in_len| is the number of hex digits.
|
||||
if (!bn_expand(bn, in_len * 4)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int i = 0;
|
||||
while (in_len > 0) {
|
||||
// Decode one |BN_ULONG| at a time.
|
||||
int todo = BN_BYTES * 2;
|
||||
if (todo > in_len) {
|
||||
todo = in_len;
|
||||
}
|
||||
|
||||
BN_ULONG word = 0;
|
||||
int j;
|
||||
for (j = todo; j > 0; j--) {
|
||||
char c = in[in_len - j];
|
||||
|
||||
BN_ULONG hex;
|
||||
if (c >= '0' && c <= '9') {
|
||||
hex = c - '0';
|
||||
} else if (c >= 'a' && c <= 'f') {
|
||||
hex = c - 'a' + 10;
|
||||
} else if (c >= 'A' && c <= 'F') {
|
||||
hex = c - 'A' + 10;
|
||||
} else {
|
||||
hex = 0;
|
||||
// This shouldn't happen. The caller checks |isxdigit|.
|
||||
assert(0);
|
||||
}
|
||||
word = (word << 4) | hex;
|
||||
}
|
||||
|
||||
bn->d[i++] = word;
|
||||
in_len -= todo;
|
||||
}
|
||||
assert(i <= bn->dmax);
|
||||
bn->top = i;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// decode_dec decodes |in_len| bytes of decimal data from |in| and updates |bn|.
|
||||
static int decode_dec(BIGNUM *bn, const char *in, int in_len) {
|
||||
int i, j;
|
||||
BN_ULONG l = 0;
|
||||
|
||||
// Decode |BN_DEC_NUM| digits at a time.
|
||||
j = BN_DEC_NUM - (in_len % BN_DEC_NUM);
|
||||
if (j == BN_DEC_NUM) {
|
||||
j = 0;
|
||||
}
|
||||
l = 0;
|
||||
for (i = 0; i < in_len; i++) {
|
||||
l *= 10;
|
||||
l += in[i] - '0';
|
||||
if (++j == BN_DEC_NUM) {
|
||||
if (!BN_mul_word(bn, BN_DEC_CONV) ||
|
||||
!BN_add_word(bn, l)) {
|
||||
return 0;
|
||||
}
|
||||
l = 0;
|
||||
j = 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
typedef int (*decode_func) (BIGNUM *bn, const char *in, int in_len);
|
||||
typedef int (*char_test_func) (int c);
|
||||
|
||||
static int bn_x2bn(BIGNUM **outp, const char *in, decode_func decode, char_test_func want_char) {
|
||||
BIGNUM *ret = NULL;
|
||||
int neg = 0, i;
|
||||
int num;
|
||||
|
||||
if (in == NULL || *in == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (*in == '-') {
|
||||
neg = 1;
|
||||
in++;
|
||||
}
|
||||
|
||||
for (i = 0; want_char((unsigned char)in[i]) && i + neg < INT_MAX; i++) {}
|
||||
|
||||
num = i + neg;
|
||||
if (outp == NULL) {
|
||||
return num;
|
||||
}
|
||||
|
||||
// in is the start of the hex digits, and it is 'i' long
|
||||
if (*outp == NULL) {
|
||||
ret = BN_new();
|
||||
if (ret == NULL) {
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
ret = *outp;
|
||||
BN_zero(ret);
|
||||
}
|
||||
|
||||
if (!decode(ret, in, i)) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
bn_correct_top(ret);
|
||||
if (!BN_is_zero(ret)) {
|
||||
ret->neg = neg;
|
||||
}
|
||||
|
||||
*outp = ret;
|
||||
return num;
|
||||
|
||||
err:
|
||||
if (*outp == NULL) {
|
||||
BN_free(ret);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int BN_hex2bn(BIGNUM **outp, const char *in) {
|
||||
return bn_x2bn(outp, in, decode_hex, isxdigit);
|
||||
}
|
||||
|
||||
char *BN_bn2dec(const BIGNUM *a) {
|
||||
// It is easier to print strings little-endian, so we assemble it in reverse
|
||||
// and fix at the end.
|
||||
BIGNUM *copy = NULL;
|
||||
CBB cbb;
|
||||
if (!CBB_init(&cbb, 16) ||
|
||||
!CBB_add_u8(&cbb, 0 /* trailing NUL */)) {
|
||||
goto cbb_err;
|
||||
}
|
||||
|
||||
if (BN_is_zero(a)) {
|
||||
if (!CBB_add_u8(&cbb, '0')) {
|
||||
goto cbb_err;
|
||||
}
|
||||
} else {
|
||||
copy = BN_dup(a);
|
||||
if (copy == NULL) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
while (!BN_is_zero(copy)) {
|
||||
BN_ULONG word = BN_div_word(copy, BN_DEC_CONV);
|
||||
if (word == (BN_ULONG)-1) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
const int add_leading_zeros = !BN_is_zero(copy);
|
||||
for (int i = 0; i < BN_DEC_NUM && (add_leading_zeros || word != 0); i++) {
|
||||
if (!CBB_add_u8(&cbb, '0' + word % 10)) {
|
||||
goto cbb_err;
|
||||
}
|
||||
word /= 10;
|
||||
}
|
||||
assert(word == 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (BN_is_negative(a) &&
|
||||
!CBB_add_u8(&cbb, '-')) {
|
||||
goto cbb_err;
|
||||
}
|
||||
|
||||
uint8_t *data;
|
||||
size_t len;
|
||||
if (!CBB_finish(&cbb, &data, &len)) {
|
||||
goto cbb_err;
|
||||
}
|
||||
|
||||
// Reverse the buffer.
|
||||
for (size_t i = 0; i < len/2; i++) {
|
||||
uint8_t tmp = data[i];
|
||||
data[i] = data[len - 1 - i];
|
||||
data[len - 1 - i] = tmp;
|
||||
}
|
||||
|
||||
BN_free(copy);
|
||||
return (char *)data;
|
||||
|
||||
cbb_err:
|
||||
OPENSSL_PUT_ERROR(BN, ERR_R_MALLOC_FAILURE);
|
||||
err:
|
||||
BN_free(copy);
|
||||
CBB_cleanup(&cbb);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int BN_dec2bn(BIGNUM **outp, const char *in) {
|
||||
return bn_x2bn(outp, in, decode_dec, isdigit);
|
||||
}
|
||||
|
||||
int BN_asc2bn(BIGNUM **outp, const char *in) {
|
||||
const char *const orig_in = in;
|
||||
if (*in == '-') {
|
||||
in++;
|
||||
}
|
||||
|
||||
if (in[0] == '0' && (in[1] == 'X' || in[1] == 'x')) {
|
||||
if (!BN_hex2bn(outp, in+2)) {
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
if (!BN_dec2bn(outp, in)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (*orig_in == '-' && !BN_is_zero(*outp)) {
|
||||
(*outp)->neg = 1;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int BN_print(BIO *bp, const BIGNUM *a) {
|
||||
int i, j, v, z = 0;
|
||||
int ret = 0;
|
||||
|
||||
if (a->neg && BIO_write(bp, "-", 1) != 1) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (BN_is_zero(a) && BIO_write(bp, "0", 1) != 1) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
for (i = a->top - 1; i >= 0; i--) {
|
||||
for (j = BN_BITS2 - 4; j >= 0; j -= 4) {
|
||||
// strip leading zeros
|
||||
v = ((int)(a->d[i] >> (long)j)) & 0x0f;
|
||||
if (z || v != 0) {
|
||||
if (BIO_write(bp, &hextable[v], 1) != 1) {
|
||||
goto end;
|
||||
}
|
||||
z = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
ret = 1;
|
||||
|
||||
end:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int BN_print_fp(FILE *fp, const BIGNUM *a) {
|
||||
BIO *b;
|
||||
int ret;
|
||||
|
||||
b = BIO_new(BIO_s_file());
|
||||
if (b == NULL) {
|
||||
return 0;
|
||||
}
|
||||
BIO_set_fp(b, fp, BIO_NOCLOSE);
|
||||
ret = BN_print(b, a);
|
||||
BIO_free(b);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
size_t BN_bn2mpi(const BIGNUM *in, uint8_t *out) {
|
||||
const size_t bits = BN_num_bits(in);
|
||||
const size_t bytes = (bits + 7) / 8;
|
||||
// If the number of bits is a multiple of 8, i.e. if the MSB is set,
|
||||
// prefix with a zero byte.
|
||||
int extend = 0;
|
||||
if (bytes != 0 && (bits & 0x07) == 0) {
|
||||
extend = 1;
|
||||
}
|
||||
|
||||
const size_t len = bytes + extend;
|
||||
if (len < bytes ||
|
||||
4 + len < len ||
|
||||
(len & 0xffffffff) != len) {
|
||||
// If we cannot represent the number then we emit zero as the interface
|
||||
// doesn't allow an error to be signalled.
|
||||
if (out) {
|
||||
OPENSSL_memset(out, 0, 4);
|
||||
}
|
||||
return 4;
|
||||
}
|
||||
|
||||
if (out == NULL) {
|
||||
return 4 + len;
|
||||
}
|
||||
|
||||
out[0] = len >> 24;
|
||||
out[1] = len >> 16;
|
||||
out[2] = len >> 8;
|
||||
out[3] = len;
|
||||
if (extend) {
|
||||
out[4] = 0;
|
||||
}
|
||||
BN_bn2bin(in, out + 4 + extend);
|
||||
if (in->neg && len > 0) {
|
||||
out[4] |= 0x80;
|
||||
}
|
||||
return len + 4;
|
||||
}
|
||||
|
||||
BIGNUM *BN_mpi2bn(const uint8_t *in, size_t len, BIGNUM *out) {
|
||||
if (len < 4) {
|
||||
OPENSSL_PUT_ERROR(BN, BN_R_BAD_ENCODING);
|
||||
return NULL;
|
||||
}
|
||||
const size_t in_len = ((size_t)in[0] << 24) |
|
||||
((size_t)in[1] << 16) |
|
||||
((size_t)in[2] << 8) |
|
||||
((size_t)in[3]);
|
||||
if (in_len != len - 4) {
|
||||
OPENSSL_PUT_ERROR(BN, BN_R_BAD_ENCODING);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int out_is_alloced = 0;
|
||||
if (out == NULL) {
|
||||
out = BN_new();
|
||||
if (out == NULL) {
|
||||
OPENSSL_PUT_ERROR(BN, ERR_R_MALLOC_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
out_is_alloced = 1;
|
||||
}
|
||||
|
||||
if (in_len == 0) {
|
||||
BN_zero(out);
|
||||
return out;
|
||||
}
|
||||
|
||||
in += 4;
|
||||
if (BN_bin2bn(in, in_len, out) == NULL) {
|
||||
if (out_is_alloced) {
|
||||
BN_free(out);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
out->neg = ((*in) & 0x80) != 0;
|
||||
if (out->neg) {
|
||||
BN_clear_bit(out, BN_num_bits(out) - 1);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
+14
-16
@@ -97,14 +97,14 @@ static int buf_mem_reserve(BUF_MEM *buf, size_t cap, int clean) {
|
||||
|
||||
size_t n = cap + 3;
|
||||
if (n < cap) {
|
||||
/* overflow */
|
||||
// overflow
|
||||
OPENSSL_PUT_ERROR(BUF, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
n = n / 3;
|
||||
size_t alloc_size = n * 4;
|
||||
if (alloc_size / 4 != n) {
|
||||
/* overflow */
|
||||
// overflow
|
||||
OPENSSL_PUT_ERROR(BUF, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
@@ -153,12 +153,12 @@ size_t BUF_MEM_grow_clean(BUF_MEM *buf, size_t len) {
|
||||
return buf_mem_grow(buf, len, 1 /* clear old buffer contents. */);
|
||||
}
|
||||
|
||||
char *BUF_strdup(const char *buf) {
|
||||
if (buf == NULL) {
|
||||
char *BUF_strdup(const char *str) {
|
||||
if (str == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return BUF_strndup(buf, strlen(buf));
|
||||
return BUF_strndup(str, strlen(str));
|
||||
}
|
||||
|
||||
size_t BUF_strnlen(const char *str, size_t max_len) {
|
||||
@@ -173,19 +173,19 @@ size_t BUF_strnlen(const char *str, size_t max_len) {
|
||||
return i;
|
||||
}
|
||||
|
||||
char *BUF_strndup(const char *buf, size_t size) {
|
||||
char *BUF_strndup(const char *str, size_t size) {
|
||||
char *ret;
|
||||
size_t alloc_size;
|
||||
|
||||
if (buf == NULL) {
|
||||
if (str == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
size = BUF_strnlen(buf, size);
|
||||
size = BUF_strnlen(str, size);
|
||||
|
||||
alloc_size = size + 1;
|
||||
if (alloc_size < size) {
|
||||
/* overflow */
|
||||
// overflow
|
||||
OPENSSL_PUT_ERROR(BUF, ERR_R_MALLOC_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
@@ -195,7 +195,7 @@ char *BUF_strndup(const char *buf, size_t size) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
OPENSSL_memcpy(ret, buf, size);
|
||||
OPENSSL_memcpy(ret, str, size);
|
||||
ret[size] = '\0';
|
||||
return ret;
|
||||
}
|
||||
@@ -223,19 +223,17 @@ size_t BUF_strlcat(char *dst, const char *src, size_t dst_size) {
|
||||
return l + BUF_strlcpy(dst, src, dst_size);
|
||||
}
|
||||
|
||||
void *BUF_memdup(const void *data, size_t dst_size) {
|
||||
void *ret;
|
||||
|
||||
if (dst_size == 0) {
|
||||
void *BUF_memdup(const void *data, size_t size) {
|
||||
if (size == 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret = OPENSSL_malloc(dst_size);
|
||||
void *ret = OPENSSL_malloc(size);
|
||||
if (ret == NULL) {
|
||||
OPENSSL_PUT_ERROR(BUF, ERR_R_MALLOC_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
OPENSSL_memcpy(ret, data, dst_size);
|
||||
OPENSSL_memcpy(ret, data, size);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -10,14 +10,3 @@ add_library(
|
||||
cbs.c
|
||||
cbb.c
|
||||
)
|
||||
|
||||
add_executable(
|
||||
bytestring_test
|
||||
|
||||
bytestring_test.cc
|
||||
|
||||
$<TARGET_OBJECTS:test_support>
|
||||
)
|
||||
|
||||
target_link_libraries(bytestring_test crypto)
|
||||
add_dependencies(all_tests bytestring_test)
|
||||
|
||||
+35
-35
@@ -21,13 +21,13 @@
|
||||
#include "../internal.h"
|
||||
|
||||
|
||||
/* kMaxDepth is a just a sanity limit. The code should be such that the length
|
||||
* of the input being processes always decreases. None the less, a very large
|
||||
* input could otherwise cause the stack to overflow. */
|
||||
// kMaxDepth is a just a sanity limit. The code should be such that the length
|
||||
// of the input being processes always decreases. None the less, a very large
|
||||
// input could otherwise cause the stack to overflow.
|
||||
static const unsigned kMaxDepth = 2048;
|
||||
|
||||
/* is_string_type returns one if |tag| is a string type and zero otherwise. It
|
||||
* ignores the constructed bit. */
|
||||
// is_string_type returns one if |tag| is a string type and zero otherwise. It
|
||||
// ignores the constructed bit.
|
||||
static int is_string_type(unsigned tag) {
|
||||
if ((tag & 0xc0) != 0) {
|
||||
return 0;
|
||||
@@ -38,7 +38,7 @@ static int is_string_type(unsigned tag) {
|
||||
case CBS_ASN1_UTF8STRING:
|
||||
case CBS_ASN1_NUMERICSTRING:
|
||||
case CBS_ASN1_PRINTABLESTRING:
|
||||
case CBS_ASN1_T16STRING:
|
||||
case CBS_ASN1_T61STRING:
|
||||
case CBS_ASN1_VIDEOTEXSTRING:
|
||||
case CBS_ASN1_IA5STRING:
|
||||
case CBS_ASN1_GRAPHICSTRING:
|
||||
@@ -52,10 +52,10 @@ static int is_string_type(unsigned tag) {
|
||||
}
|
||||
}
|
||||
|
||||
/* cbs_find_ber walks an ASN.1 structure in |orig_in| and sets |*ber_found|
|
||||
* depending on whether an indefinite length element or constructed string was
|
||||
* found. The value of |orig_in| is not changed. It returns one on success (i.e.
|
||||
* |*ber_found| was set) and zero on error. */
|
||||
// cbs_find_ber walks an ASN.1 structure in |orig_in| and sets |*ber_found|
|
||||
// depending on whether an indefinite length element or constructed string was
|
||||
// found. The value of |orig_in| is not changed. It returns one on success (i.e.
|
||||
// |*ber_found| was set) and zero on error.
|
||||
static int cbs_find_ber(const CBS *orig_in, char *ber_found, unsigned depth) {
|
||||
CBS in;
|
||||
|
||||
@@ -77,13 +77,13 @@ static int cbs_find_ber(const CBS *orig_in, char *ber_found, unsigned depth) {
|
||||
if (CBS_len(&contents) == header_len &&
|
||||
header_len > 0 &&
|
||||
CBS_data(&contents)[header_len-1] == 0x80) {
|
||||
/* Found an indefinite-length element. */
|
||||
// Found an indefinite-length element.
|
||||
*ber_found = 1;
|
||||
return 1;
|
||||
}
|
||||
if (tag & CBS_ASN1_CONSTRUCTED) {
|
||||
if (is_string_type(tag)) {
|
||||
/* Constructed strings are only legal in BER and require conversion. */
|
||||
// Constructed strings are only legal in BER and require conversion.
|
||||
*ber_found = 1;
|
||||
return 1;
|
||||
}
|
||||
@@ -97,20 +97,20 @@ static int cbs_find_ber(const CBS *orig_in, char *ber_found, unsigned depth) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* is_eoc returns true if |header_len| and |contents|, as returned by
|
||||
* |CBS_get_any_ber_asn1_element|, indicate an "end of contents" (EOC) value. */
|
||||
// is_eoc returns true if |header_len| and |contents|, as returned by
|
||||
// |CBS_get_any_ber_asn1_element|, indicate an "end of contents" (EOC) value.
|
||||
static char is_eoc(size_t header_len, CBS *contents) {
|
||||
return header_len == 2 && CBS_len(contents) == 2 &&
|
||||
OPENSSL_memcmp(CBS_data(contents), "\x00\x00", 2) == 0;
|
||||
}
|
||||
|
||||
/* cbs_convert_ber reads BER data from |in| and writes DER data to |out|. If
|
||||
* |string_tag| is non-zero, then all elements must match |string_tag| up to the
|
||||
* constructed bit and primitive element bodies are written to |out| without
|
||||
* element headers. This is used when concatenating the fragments of a
|
||||
* constructed string. If |looking_for_eoc| is set then any EOC elements found
|
||||
* will cause the function to return after consuming it. It returns one on
|
||||
* success and zero on error. */
|
||||
// cbs_convert_ber reads BER data from |in| and writes DER data to |out|. If
|
||||
// |string_tag| is non-zero, then all elements must match |string_tag| up to the
|
||||
// constructed bit and primitive element bodies are written to |out| without
|
||||
// element headers. This is used when concatenating the fragments of a
|
||||
// constructed string. If |looking_for_eoc| is set then any EOC elements found
|
||||
// will cause the function to return after consuming it. It returns one on
|
||||
// success and zero on error.
|
||||
static int cbs_convert_ber(CBS *in, CBB *out, unsigned string_tag,
|
||||
char looking_for_eoc, unsigned depth) {
|
||||
assert(!(string_tag & CBS_ASN1_CONSTRUCTED));
|
||||
@@ -134,9 +134,9 @@ static int cbs_convert_ber(CBS *in, CBB *out, unsigned string_tag,
|
||||
}
|
||||
|
||||
if (string_tag != 0) {
|
||||
/* This is part of a constructed string. All elements must match
|
||||
* |string_tag| up to the constructed bit and get appended to |out|
|
||||
* without a child element. */
|
||||
// This is part of a constructed string. All elements must match
|
||||
// |string_tag| up to the constructed bit and get appended to |out|
|
||||
// without a child element.
|
||||
if ((tag & ~CBS_ASN1_CONSTRUCTED) != string_tag) {
|
||||
return 0;
|
||||
}
|
||||
@@ -144,8 +144,8 @@ static int cbs_convert_ber(CBS *in, CBB *out, unsigned string_tag,
|
||||
} else {
|
||||
unsigned out_tag = tag;
|
||||
if ((tag & CBS_ASN1_CONSTRUCTED) && is_string_type(tag)) {
|
||||
/* If a constructed string, clear the constructed bit and inform
|
||||
* children to concatenate bodies. */
|
||||
// If a constructed string, clear the constructed bit and inform
|
||||
// children to concatenate bodies.
|
||||
out_tag &= ~CBS_ASN1_CONSTRUCTED;
|
||||
child_string_tag = out_tag;
|
||||
}
|
||||
@@ -157,7 +157,7 @@ static int cbs_convert_ber(CBS *in, CBB *out, unsigned string_tag,
|
||||
|
||||
if (CBS_len(&contents) == header_len && header_len > 0 &&
|
||||
CBS_data(&contents)[header_len - 1] == 0x80) {
|
||||
/* This is an indefinite length element. */
|
||||
// This is an indefinite length element.
|
||||
if (!cbs_convert_ber(in, out_contents, child_string_tag,
|
||||
1 /* looking for eoc */, depth + 1) ||
|
||||
!CBB_flush(out)) {
|
||||
@@ -171,13 +171,13 @@ static int cbs_convert_ber(CBS *in, CBB *out, unsigned string_tag,
|
||||
}
|
||||
|
||||
if (tag & CBS_ASN1_CONSTRUCTED) {
|
||||
/* Recurse into children. */
|
||||
// Recurse into children.
|
||||
if (!cbs_convert_ber(&contents, out_contents, child_string_tag,
|
||||
0 /* not looking for eoc */, depth + 1)) {
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
/* Copy primitive contents as-is. */
|
||||
// Copy primitive contents as-is.
|
||||
if (!CBB_add_bytes(out_contents, CBS_data(&contents),
|
||||
CBS_len(&contents))) {
|
||||
return 0;
|
||||
@@ -195,8 +195,8 @@ static int cbs_convert_ber(CBS *in, CBB *out, unsigned string_tag,
|
||||
int CBS_asn1_ber_to_der(CBS *in, uint8_t **out, size_t *out_len) {
|
||||
CBB cbb;
|
||||
|
||||
/* First, do a quick walk to find any indefinite-length elements. Most of the
|
||||
* time we hope that there aren't any and thus we can quickly return. */
|
||||
// First, do a quick walk to find any indefinite-length elements. Most of the
|
||||
// time we hope that there aren't any and thus we can quickly return.
|
||||
char conversion_needed;
|
||||
if (!cbs_find_ber(in, &conversion_needed, 0)) {
|
||||
return 0;
|
||||
@@ -225,14 +225,14 @@ int CBS_get_asn1_implicit_string(CBS *in, CBS *out, uint8_t **out_storage,
|
||||
assert(is_string_type(inner_tag));
|
||||
|
||||
if (CBS_peek_asn1_tag(in, outer_tag)) {
|
||||
/* Normal implicitly-tagged string. */
|
||||
// Normal implicitly-tagged string.
|
||||
*out_storage = NULL;
|
||||
return CBS_get_asn1(in, out, outer_tag);
|
||||
}
|
||||
|
||||
/* Otherwise, try to parse an implicitly-tagged constructed string.
|
||||
* |CBS_asn1_ber_to_der| is assumed to have run, so only allow one level deep
|
||||
* of nesting. */
|
||||
// Otherwise, try to parse an implicitly-tagged constructed string.
|
||||
// |CBS_asn1_ber_to_der| is assumed to have run, so only allow one level deep
|
||||
// of nesting.
|
||||
CBB result;
|
||||
CBS child;
|
||||
if (!CBB_init(&result, CBS_len(in)) ||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
+24
-24
@@ -27,7 +27,7 @@ void CBB_zero(CBB *cbb) {
|
||||
}
|
||||
|
||||
static int cbb_init(CBB *cbb, uint8_t *buf, size_t cap) {
|
||||
/* This assumes that |cbb| has already been zeroed. */
|
||||
// This assumes that |cbb| has already been zeroed.
|
||||
struct cbb_buffer_st *base;
|
||||
|
||||
base = OPENSSL_malloc(sizeof(struct cbb_buffer_st));
|
||||
@@ -75,8 +75,8 @@ int CBB_init_fixed(CBB *cbb, uint8_t *buf, size_t len) {
|
||||
|
||||
void CBB_cleanup(CBB *cbb) {
|
||||
if (cbb->base) {
|
||||
/* Only top-level |CBB|s are cleaned up. Child |CBB|s are non-owning. They
|
||||
* are implicitly discarded when the parent is flushed or cleaned up. */
|
||||
// Only top-level |CBB|s are cleaned up. Child |CBB|s are non-owning. They
|
||||
// are implicitly discarded when the parent is flushed or cleaned up.
|
||||
assert(cbb->is_top_level);
|
||||
|
||||
if (cbb->base->can_resize) {
|
||||
@@ -97,7 +97,7 @@ static int cbb_buffer_reserve(struct cbb_buffer_st *base, uint8_t **out,
|
||||
|
||||
newlen = base->len + len;
|
||||
if (newlen < base->len) {
|
||||
/* Overflow */
|
||||
// Overflow
|
||||
goto err;
|
||||
}
|
||||
|
||||
@@ -137,7 +137,7 @@ static int cbb_buffer_add(struct cbb_buffer_st *base, uint8_t **out,
|
||||
if (!cbb_buffer_reserve(base, out, len)) {
|
||||
return 0;
|
||||
}
|
||||
/* This will not overflow or |cbb_buffer_reserve| would have failed. */
|
||||
// This will not overflow or |cbb_buffer_reserve| would have failed.
|
||||
base->len += len;
|
||||
return 1;
|
||||
}
|
||||
@@ -176,7 +176,7 @@ int CBB_finish(CBB *cbb, uint8_t **out_data, size_t *out_len) {
|
||||
}
|
||||
|
||||
if (cbb->base->can_resize && (out_data == NULL || out_len == NULL)) {
|
||||
/* |out_data| and |out_len| can only be NULL if the CBB is fixed. */
|
||||
// |out_data| and |out_len| can only be NULL if the CBB is fixed.
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -191,15 +191,15 @@ int CBB_finish(CBB *cbb, uint8_t **out_data, size_t *out_len) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* CBB_flush recurses and then writes out any pending length prefix. The
|
||||
* current length of the underlying base is taken to be the length of the
|
||||
* length-prefixed data. */
|
||||
// CBB_flush recurses and then writes out any pending length prefix. The
|
||||
// current length of the underlying base is taken to be the length of the
|
||||
// length-prefixed data.
|
||||
int CBB_flush(CBB *cbb) {
|
||||
size_t child_start, i, len;
|
||||
|
||||
/* If |cbb->base| has hit an error, the buffer is in an undefined state, so
|
||||
* fail all following calls. In particular, |cbb->child| may point to invalid
|
||||
* memory. */
|
||||
// If |cbb->base| has hit an error, the buffer is in an undefined state, so
|
||||
// fail all following calls. In particular, |cbb->child| may point to invalid
|
||||
// memory.
|
||||
if (cbb->base == NULL || cbb->base->error) {
|
||||
return 0;
|
||||
}
|
||||
@@ -219,16 +219,16 @@ int CBB_flush(CBB *cbb) {
|
||||
len = cbb->base->len - child_start;
|
||||
|
||||
if (cbb->child->pending_is_asn1) {
|
||||
/* For ASN.1 we assume that we'll only need a single byte for the length.
|
||||
* If that turned out to be incorrect, we have to move the contents along
|
||||
* in order to make space. */
|
||||
// For ASN.1 we assume that we'll only need a single byte for the length.
|
||||
// If that turned out to be incorrect, we have to move the contents along
|
||||
// in order to make space.
|
||||
uint8_t len_len;
|
||||
uint8_t initial_length_byte;
|
||||
|
||||
assert (cbb->child->pending_len_len == 1);
|
||||
|
||||
if (len > 0xfffffffe) {
|
||||
/* Too large. */
|
||||
// Too large.
|
||||
goto err;
|
||||
} else if (len > 0xffffff) {
|
||||
len_len = 5;
|
||||
@@ -249,7 +249,7 @@ int CBB_flush(CBB *cbb) {
|
||||
}
|
||||
|
||||
if (len_len != 1) {
|
||||
/* We need to move the contents along in order to make space. */
|
||||
// We need to move the contents along in order to make space.
|
||||
size_t extra_bytes = len_len - 1;
|
||||
if (!cbb_buffer_add(cbb->base, NULL, extra_bytes)) {
|
||||
goto err;
|
||||
@@ -331,14 +331,14 @@ int CBB_add_u24_length_prefixed(CBB *cbb, CBB *out_contents) {
|
||||
int CBB_add_asn1(CBB *cbb, CBB *out_contents, unsigned tag) {
|
||||
if (tag > 0xff ||
|
||||
(tag & 0x1f) == 0x1f) {
|
||||
/* Long form identifier octets are not supported. Further, all current valid
|
||||
* tag serializations are 8 bits. */
|
||||
// Long form identifier octets are not supported. Further, all current valid
|
||||
// tag serializations are 8 bits.
|
||||
cbb->base->error = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!CBB_flush(cbb) ||
|
||||
/* |tag|'s representation matches the DER encoding. */
|
||||
// |tag|'s representation matches the DER encoding.
|
||||
!CBB_add_u8(cbb, (uint8_t)tag)) {
|
||||
return 0;
|
||||
}
|
||||
@@ -451,11 +451,11 @@ int CBB_add_asn1_uint64(CBB *cbb, uint64_t value) {
|
||||
uint8_t byte = (value >> 8*(7-i)) & 0xff;
|
||||
if (!started) {
|
||||
if (byte == 0) {
|
||||
/* Don't encode leading zeros. */
|
||||
// Don't encode leading zeros.
|
||||
continue;
|
||||
}
|
||||
/* If the high bit is set, add a padding byte to make it
|
||||
* unsigned. */
|
||||
// If the high bit is set, add a padding byte to make it
|
||||
// unsigned.
|
||||
if ((byte & 0x80) && !CBB_add_u8(&child, 0)) {
|
||||
return 0;
|
||||
}
|
||||
@@ -466,7 +466,7 @@ int CBB_add_asn1_uint64(CBB *cbb, uint64_t value) {
|
||||
}
|
||||
}
|
||||
|
||||
/* 0 is encoded as a single 0, not the empty string. */
|
||||
// 0 is encoded as a single 0, not the empty string.
|
||||
if (!started && !CBB_add_u8(&child, 0)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
+33
-37
@@ -190,13 +190,13 @@ static int cbs_get_any_asn1_element(CBS *cbs, CBS *out, unsigned *out_tag,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ITU-T X.690 section 8.1.2.3 specifies the format for identifiers with a tag
|
||||
* number no greater than 30.
|
||||
*
|
||||
* If the number portion is 31 (0x1f, the largest value that fits in the
|
||||
* allotted bits), then the tag is more than one byte long and the
|
||||
* continuation bytes contain the tag number. This parser only supports tag
|
||||
* numbers less than 31 (and thus single-byte tags). */
|
||||
// ITU-T X.690 section 8.1.2.3 specifies the format for identifiers with a tag
|
||||
// number no greater than 30.
|
||||
//
|
||||
// If the number portion is 31 (0x1f, the largest value that fits in the
|
||||
// allotted bits), then the tag is more than one byte long and the
|
||||
// continuation bytes contain the tag number. This parser only supports tag
|
||||
// numbers less than 31 (and thus single-byte tags).
|
||||
if ((tag & 0x1f) == 0x1f) {
|
||||
return 0;
|
||||
}
|
||||
@@ -206,52 +206,51 @@ static int cbs_get_any_asn1_element(CBS *cbs, CBS *out, unsigned *out_tag,
|
||||
}
|
||||
|
||||
size_t len;
|
||||
/* The format for the length encoding is specified in ITU-T X.690 section
|
||||
* 8.1.3. */
|
||||
// The format for the length encoding is specified in ITU-T X.690 section
|
||||
// 8.1.3.
|
||||
if ((length_byte & 0x80) == 0) {
|
||||
/* Short form length. */
|
||||
// Short form length.
|
||||
len = ((size_t) length_byte) + 2;
|
||||
if (out_header_len != NULL) {
|
||||
*out_header_len = 2;
|
||||
}
|
||||
} else {
|
||||
/* The high bit indicate that this is the long form, while the next 7 bits
|
||||
* encode the number of subsequent octets used to encode the length (ITU-T
|
||||
* X.690 clause 8.1.3.5.b). */
|
||||
// The high bit indicate that this is the long form, while the next 7 bits
|
||||
// encode the number of subsequent octets used to encode the length (ITU-T
|
||||
// X.690 clause 8.1.3.5.b).
|
||||
const size_t num_bytes = length_byte & 0x7f;
|
||||
uint32_t len32;
|
||||
|
||||
if (ber_ok && (tag & CBS_ASN1_CONSTRUCTED) != 0 && num_bytes == 0) {
|
||||
/* indefinite length */
|
||||
// indefinite length
|
||||
if (out_header_len != NULL) {
|
||||
*out_header_len = 2;
|
||||
}
|
||||
return CBS_get_bytes(cbs, out, 2);
|
||||
}
|
||||
|
||||
/* ITU-T X.690 clause 8.1.3.5.c specifies that the value 0xff shall not be
|
||||
* used as the first byte of the length. If this parser encounters that
|
||||
* value, num_bytes will be parsed as 127, which will fail the check below.
|
||||
*/
|
||||
// ITU-T X.690 clause 8.1.3.5.c specifies that the value 0xff shall not be
|
||||
// used as the first byte of the length. If this parser encounters that
|
||||
// value, num_bytes will be parsed as 127, which will fail the check below.
|
||||
if (num_bytes == 0 || num_bytes > 4) {
|
||||
return 0;
|
||||
}
|
||||
if (!cbs_get_u(&header, &len32, num_bytes)) {
|
||||
return 0;
|
||||
}
|
||||
/* ITU-T X.690 section 10.1 (DER length forms) requires encoding the length
|
||||
* with the minimum number of octets. */
|
||||
// ITU-T X.690 section 10.1 (DER length forms) requires encoding the length
|
||||
// with the minimum number of octets.
|
||||
if (len32 < 128) {
|
||||
/* Length should have used short-form encoding. */
|
||||
// Length should have used short-form encoding.
|
||||
return 0;
|
||||
}
|
||||
if ((len32 >> ((num_bytes-1)*8)) == 0) {
|
||||
/* Length should have been at least one byte shorter. */
|
||||
// Length should have been at least one byte shorter.
|
||||
return 0;
|
||||
}
|
||||
len = len32;
|
||||
if (len + 2 + num_bytes < len) {
|
||||
/* Overflow. */
|
||||
// Overflow.
|
||||
return 0;
|
||||
}
|
||||
len += 2 + num_bytes;
|
||||
@@ -329,35 +328,32 @@ int CBS_peek_asn1_tag(const CBS *cbs, unsigned tag_value) {
|
||||
|
||||
int CBS_get_asn1_uint64(CBS *cbs, uint64_t *out) {
|
||||
CBS bytes;
|
||||
const uint8_t *data;
|
||||
size_t i, len;
|
||||
|
||||
if (!CBS_get_asn1(cbs, &bytes, CBS_ASN1_INTEGER)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
*out = 0;
|
||||
data = CBS_data(&bytes);
|
||||
len = CBS_len(&bytes);
|
||||
const uint8_t *data = CBS_data(&bytes);
|
||||
size_t len = CBS_len(&bytes);
|
||||
|
||||
if (len == 0) {
|
||||
/* An INTEGER is encoded with at least one octet. */
|
||||
// An INTEGER is encoded with at least one octet.
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((data[0] & 0x80) != 0) {
|
||||
/* Negative number. */
|
||||
// Negative number.
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (data[0] == 0 && len > 1 && (data[1] & 0x80) == 0) {
|
||||
/* Extra leading zeros. */
|
||||
// Extra leading zeros.
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
if ((*out >> 56) != 0) {
|
||||
/* Too large to represent as a uint64_t. */
|
||||
// Too large to represent as a uint64_t.
|
||||
return 0;
|
||||
}
|
||||
*out <<= 8;
|
||||
@@ -465,7 +461,7 @@ int CBS_is_valid_asn1_bitstring(const CBS *cbs) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* All num_unused_bits bits must exist and be zeros. */
|
||||
// All num_unused_bits bits must exist and be zeros.
|
||||
uint8_t last;
|
||||
if (!CBS_get_last_u8(&in, &last) ||
|
||||
(last & ((1 << num_unused_bits) - 1)) != 0) {
|
||||
@@ -483,9 +479,9 @@ int CBS_asn1_bitstring_has_bit(const CBS *cbs, unsigned bit) {
|
||||
const unsigned byte_num = (bit >> 3) + 1;
|
||||
const unsigned bit_num = 7 - (bit & 7);
|
||||
|
||||
/* Unused bits are zero, and this function does not distinguish between
|
||||
* missing and unset bits. Thus it is sufficient to do a byte-level length
|
||||
* check. */
|
||||
// Unused bits are zero, and this function does not distinguish between
|
||||
// missing and unset bits. Thus it is sufficient to do a byte-level length
|
||||
// check.
|
||||
return byte_num < CBS_len(cbs) &&
|
||||
(CBS_data(cbs)[byte_num] & (1 << bit_num)) != 0;
|
||||
}
|
||||
|
||||
@@ -22,54 +22,54 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/* CBS_asn1_ber_to_der reads a BER element from |in|. If it finds
|
||||
* indefinite-length elements or constructed strings then it converts the BER
|
||||
* data to DER and sets |*out| and |*out_length| to describe a malloced buffer
|
||||
* containing the DER data. Additionally, |*in| will be advanced over the BER
|
||||
* element.
|
||||
*
|
||||
* If it doesn't find any indefinite-length elements or constructed strings then
|
||||
* it sets |*out| to NULL and |*in| is unmodified.
|
||||
*
|
||||
* This function should successfully process any valid BER input, however it
|
||||
* will not convert all of BER's deviations from DER. BER is ambiguous between
|
||||
* implicitly-tagged SEQUENCEs of strings and implicitly-tagged constructed
|
||||
* strings. Implicitly-tagged strings must be parsed with
|
||||
* |CBS_get_ber_implicitly_tagged_string| instead of |CBS_get_asn1|. The caller
|
||||
* must also account for BER variations in the contents of a primitive.
|
||||
*
|
||||
* It returns one on success and zero otherwise. */
|
||||
// CBS_asn1_ber_to_der reads a BER element from |in|. If it finds
|
||||
// indefinite-length elements or constructed strings then it converts the BER
|
||||
// data to DER and sets |*out| and |*out_length| to describe a malloced buffer
|
||||
// containing the DER data. Additionally, |*in| will be advanced over the BER
|
||||
// element.
|
||||
//
|
||||
// If it doesn't find any indefinite-length elements or constructed strings then
|
||||
// it sets |*out| to NULL and |*in| is unmodified.
|
||||
//
|
||||
// This function should successfully process any valid BER input, however it
|
||||
// will not convert all of BER's deviations from DER. BER is ambiguous between
|
||||
// implicitly-tagged SEQUENCEs of strings and implicitly-tagged constructed
|
||||
// strings. Implicitly-tagged strings must be parsed with
|
||||
// |CBS_get_ber_implicitly_tagged_string| instead of |CBS_get_asn1|. The caller
|
||||
// must also account for BER variations in the contents of a primitive.
|
||||
//
|
||||
// It returns one on success and zero otherwise.
|
||||
OPENSSL_EXPORT int CBS_asn1_ber_to_der(CBS *in, uint8_t **out, size_t *out_len);
|
||||
|
||||
/* CBS_get_asn1_implicit_string parses a BER string of primitive type
|
||||
* |inner_tag| implicitly-tagged with |outer_tag|. It sets |out| to the
|
||||
* contents. If concatenation was needed, it sets |*out_storage| to a buffer
|
||||
* which the caller must release with |OPENSSL_free|. Otherwise, it sets
|
||||
* |*out_storage| to NULL.
|
||||
*
|
||||
* This function does not parse all of BER. It requires the string be
|
||||
* definite-length. Constructed strings are allowed, but all children of the
|
||||
* outermost element must be primitive. The caller should use
|
||||
* |CBS_asn1_ber_to_der| before running this function.
|
||||
*
|
||||
* It returns one on success and zero otherwise. */
|
||||
// CBS_get_asn1_implicit_string parses a BER string of primitive type
|
||||
// |inner_tag| implicitly-tagged with |outer_tag|. It sets |out| to the
|
||||
// contents. If concatenation was needed, it sets |*out_storage| to a buffer
|
||||
// which the caller must release with |OPENSSL_free|. Otherwise, it sets
|
||||
// |*out_storage| to NULL.
|
||||
//
|
||||
// This function does not parse all of BER. It requires the string be
|
||||
// definite-length. Constructed strings are allowed, but all children of the
|
||||
// outermost element must be primitive. The caller should use
|
||||
// |CBS_asn1_ber_to_der| before running this function.
|
||||
//
|
||||
// It returns one on success and zero otherwise.
|
||||
OPENSSL_EXPORT int CBS_get_asn1_implicit_string(CBS *in, CBS *out,
|
||||
uint8_t **out_storage,
|
||||
unsigned outer_tag,
|
||||
unsigned inner_tag);
|
||||
|
||||
/* CBB_finish_i2d calls |CBB_finish| on |cbb| which must have been initialized
|
||||
* with |CBB_init|. If |outp| is not NULL then the result is written to |*outp|
|
||||
* and |*outp| is advanced just past the output. It returns the number of bytes
|
||||
* in the result, whether written or not, or a negative value on error. On
|
||||
* error, it calls |CBB_cleanup| on |cbb|.
|
||||
*
|
||||
* This function may be used to help implement legacy i2d ASN.1 functions. */
|
||||
// CBB_finish_i2d calls |CBB_finish| on |cbb| which must have been initialized
|
||||
// with |CBB_init|. If |outp| is not NULL then the result is written to |*outp|
|
||||
// and |*outp| is advanced just past the output. It returns the number of bytes
|
||||
// in the result, whether written or not, or a negative value on error. On
|
||||
// error, it calls |CBB_cleanup| on |cbb|.
|
||||
//
|
||||
// This function may be used to help implement legacy i2d ASN.1 functions.
|
||||
int CBB_finish_i2d(CBB *cbb, uint8_t **outp);
|
||||
|
||||
|
||||
#if defined(__cplusplus)
|
||||
} /* extern C */
|
||||
} // extern C
|
||||
#endif
|
||||
|
||||
#endif /* OPENSSL_HEADER_BYTESTRING_INTERNAL_H */
|
||||
#endif // OPENSSL_HEADER_BYTESTRING_INTERNAL_H
|
||||
|
||||
@@ -1,4 +1,11 @@
|
||||
#!/usr/bin/env perl
|
||||
#! /usr/bin/env perl
|
||||
# Copyright 2016 The OpenSSL Project Authors. All Rights Reserved.
|
||||
#
|
||||
# Licensed under the OpenSSL license (the "License"). You may not use
|
||||
# this file except in compliance with the License. You can obtain a copy
|
||||
# in the file LICENSE in the source distribution or at
|
||||
# https://www.openssl.org/source/license.html
|
||||
|
||||
#
|
||||
# ====================================================================
|
||||
# Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
|
||||
@@ -165,8 +172,10 @@ $code.=<<___;
|
||||
#include <openssl/arm_arch.h>
|
||||
|
||||
.text
|
||||
#if defined(__thumb2__)
|
||||
#if defined(__thumb2__) || defined(__clang__)
|
||||
.syntax unified
|
||||
#endif
|
||||
#if defined(__thumb2__)
|
||||
.thumb
|
||||
#else
|
||||
.code 32
|
||||
|
||||
@@ -1,4 +1,11 @@
|
||||
#!/usr/bin/env perl
|
||||
#! /usr/bin/env perl
|
||||
# Copyright 2016 The OpenSSL Project Authors. All Rights Reserved.
|
||||
#
|
||||
# Licensed under the OpenSSL license (the "License"). You may not use
|
||||
# this file except in compliance with the License. You can obtain a copy
|
||||
# in the file LICENSE in the source distribution or at
|
||||
# https://www.openssl.org/source/license.html
|
||||
|
||||
#
|
||||
# ====================================================================
|
||||
# Written by Andy Polyakov <appro@openssl.org> for the OpenSSL
|
||||
@@ -20,6 +27,7 @@
|
||||
# Cortex-A57 8.06/+43% 4.90 4.43(**)
|
||||
# Denver 4.50/+82% 2.63 2.67(*)
|
||||
# X-Gene 9.50/+46% 8.82 8.89(*)
|
||||
# Mongoose 8.00/+44% 3.64 3.25
|
||||
#
|
||||
# (*) it's expected that doubling interleave factor doesn't help
|
||||
# all processors, only those with higher NEON latency and
|
||||
|
||||
@@ -38,7 +38,7 @@ require "x86asm.pl";
|
||||
$output=pop;
|
||||
open STDOUT,">$output";
|
||||
|
||||
&asm_init($ARGV[0],"chacha-x86.pl",$ARGV[$#ARGV] eq "386");
|
||||
&asm_init($ARGV[0],$ARGV[$#ARGV] eq "386");
|
||||
|
||||
$xmm=$ymm=1;
|
||||
$gasver=999; # enable everything
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
#
|
||||
# Performance in cycles per byte out of large buffer.
|
||||
#
|
||||
# IALU/gcc 4.8(i) 1xSSSE3/SSE2 4xSSSE3 8xAVX2
|
||||
# IALU/gcc 4.8(i) 1xSSSE3/SSE2 4xSSSE3 NxAVX(v)
|
||||
#
|
||||
# P4 9.48/+99% -/22.7(ii) -
|
||||
# Core2 7.83/+55% 7.90/8.08 4.35
|
||||
@@ -32,11 +32,13 @@
|
||||
# Sandy Bridge 8.31/+42% 5.45/6.76 2.72
|
||||
# Ivy Bridge 6.71/+46% 5.40/6.49 2.41
|
||||
# Haswell 5.92/+43% 5.20/6.45 2.42 1.23
|
||||
# Skylake 5.87/+39% 4.70/- 2.31 1.19
|
||||
# Skylake[-X] 5.87/+39% 4.70/- 2.31 1.19[0.57]
|
||||
# Silvermont 12.0/+33% 7.75/7.40 7.03(iii)
|
||||
# Knights L 11.7/- - 9.60(iii) 0.80
|
||||
# Goldmont 10.6/+17% 5.10/- 3.28
|
||||
# Sledgehammer 7.28/+52% -/14.2(ii) -
|
||||
# Bulldozer 9.66/+28% 9.85/11.1 3.06(iv)
|
||||
# Ryzen 5.96/+50% 5.19/- 2.40 2.09
|
||||
# VIA Nano 10.5/+46% 6.72/8.60 6.05
|
||||
#
|
||||
# (i) compared to older gcc 3.x one can observe >2x improvement on
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
|
||||
|
||||
/* Adapted from the public domain, estream code by D. Bernstein. */
|
||||
// Adapted from the public domain, estream code by D. Bernstein.
|
||||
|
||||
#include <openssl/chacha.h>
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
(defined(OPENSSL_X86) || defined(OPENSSL_X86_64) || \
|
||||
defined(OPENSSL_ARM) || defined(OPENSSL_AARCH64))
|
||||
|
||||
/* ChaCha20_ctr32 is defined in asm/chacha-*.pl. */
|
||||
// ChaCha20_ctr32 is defined in asm/chacha-*.pl.
|
||||
void ChaCha20_ctr32(uint8_t *out, const uint8_t *in, size_t in_len,
|
||||
const uint32_t key[8], const uint32_t counter[4]);
|
||||
|
||||
@@ -48,7 +48,7 @@ void CRYPTO_chacha_20(uint8_t *out, const uint8_t *in, size_t in_len,
|
||||
|
||||
const uint32_t *key_ptr = (const uint32_t *)key;
|
||||
#if !defined(OPENSSL_X86) && !defined(OPENSSL_X86_64)
|
||||
/* The assembly expects the key to be four-byte aligned. */
|
||||
// The assembly expects the key to be four-byte aligned.
|
||||
uint32_t key_u32[8];
|
||||
if ((((uintptr_t)key) & 3) != 0) {
|
||||
key_u32[0] = U8TO32_LITTLE(key + 0);
|
||||
@@ -69,7 +69,7 @@ void CRYPTO_chacha_20(uint8_t *out, const uint8_t *in, size_t in_len,
|
||||
|
||||
#else
|
||||
|
||||
/* sigma contains the ChaCha constants, which happen to be an ASCII string. */
|
||||
// sigma contains the ChaCha constants, which happen to be an ASCII string.
|
||||
static const uint8_t sigma[16] = { 'e', 'x', 'p', 'a', 'n', 'd', ' ', '3',
|
||||
'2', '-', 'b', 'y', 't', 'e', ' ', 'k' };
|
||||
|
||||
@@ -83,15 +83,15 @@ static const uint8_t sigma[16] = { 'e', 'x', 'p', 'a', 'n', 'd', ' ', '3',
|
||||
(p)[3] = (v >> 24) & 0xff; \
|
||||
}
|
||||
|
||||
/* QUARTERROUND updates a, b, c, d with a ChaCha "quarter" round. */
|
||||
// QUARTERROUND updates a, b, c, d with a ChaCha "quarter" round.
|
||||
#define QUARTERROUND(a, b, c, d) \
|
||||
x[a] += x[b]; x[d] = ROTATE(x[d] ^ x[a], 16); \
|
||||
x[c] += x[d]; x[b] = ROTATE(x[b] ^ x[c], 12); \
|
||||
x[a] += x[b]; x[d] = ROTATE(x[d] ^ x[a], 8); \
|
||||
x[c] += x[d]; x[b] = ROTATE(x[b] ^ x[c], 7);
|
||||
|
||||
/* chacha_core performs 20 rounds of ChaCha on the input words in
|
||||
* |input| and writes the 64 output bytes to |output|. */
|
||||
// chacha_core performs 20 rounds of ChaCha on the input words in
|
||||
// |input| and writes the 64 output bytes to |output|.
|
||||
static void chacha_core(uint8_t output[64], const uint32_t input[16]) {
|
||||
uint32_t x[16];
|
||||
int i;
|
||||
|
||||
@@ -1,52 +0,0 @@
|
||||
include_directories(../../include)
|
||||
|
||||
if (${ARCH} STREQUAL "x86_64")
|
||||
set(
|
||||
CIPHER_ARCH_SOURCES
|
||||
|
||||
chacha20_poly1305_x86_64.${ASM_EXT}
|
||||
)
|
||||
endif()
|
||||
|
||||
add_library(
|
||||
cipher
|
||||
|
||||
OBJECT
|
||||
|
||||
cipher.c
|
||||
derive_key.c
|
||||
aead.c
|
||||
|
||||
e_null.c
|
||||
e_rc2.c
|
||||
e_rc4.c
|
||||
e_des.c
|
||||
e_aes.c
|
||||
e_chacha20poly1305.c
|
||||
|
||||
tls_cbc.c
|
||||
e_tls.c
|
||||
e_ssl3.c
|
||||
|
||||
${CIPHER_ARCH_SOURCES}
|
||||
)
|
||||
|
||||
add_executable(
|
||||
cipher_test
|
||||
|
||||
cipher_test.cc
|
||||
$<TARGET_OBJECTS:test_support>
|
||||
)
|
||||
|
||||
add_executable(
|
||||
aead_test
|
||||
|
||||
aead_test.cc
|
||||
$<TARGET_OBJECTS:test_support>
|
||||
)
|
||||
|
||||
perlasm(chacha20_poly1305_x86_64.${ASM_EXT} asm/chacha20_poly1305_x86_64.pl)
|
||||
|
||||
target_link_libraries(cipher_test crypto)
|
||||
target_link_libraries(aead_test crypto)
|
||||
add_dependencies(all_tests cipher_test aead_test)
|
||||
@@ -1,156 +0,0 @@
|
||||
/* Copyright (c) 2014, Google Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
|
||||
|
||||
#include <openssl/aead.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl/cipher.h>
|
||||
#include <openssl/err.h>
|
||||
|
||||
#include "internal.h"
|
||||
#include "../internal.h"
|
||||
|
||||
|
||||
size_t EVP_AEAD_key_length(const EVP_AEAD *aead) { return aead->key_len; }
|
||||
|
||||
size_t EVP_AEAD_nonce_length(const EVP_AEAD *aead) { return aead->nonce_len; }
|
||||
|
||||
size_t EVP_AEAD_max_overhead(const EVP_AEAD *aead) { return aead->overhead; }
|
||||
|
||||
size_t EVP_AEAD_max_tag_len(const EVP_AEAD *aead) { return aead->max_tag_len; }
|
||||
|
||||
void EVP_AEAD_CTX_zero(EVP_AEAD_CTX *ctx) {
|
||||
OPENSSL_memset(ctx, 0, sizeof(EVP_AEAD_CTX));
|
||||
}
|
||||
|
||||
int EVP_AEAD_CTX_init(EVP_AEAD_CTX *ctx, const EVP_AEAD *aead,
|
||||
const uint8_t *key, size_t key_len, size_t tag_len,
|
||||
ENGINE *impl) {
|
||||
if (!aead->init) {
|
||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_NO_DIRECTION_SET);
|
||||
ctx->aead = NULL;
|
||||
return 0;
|
||||
}
|
||||
return EVP_AEAD_CTX_init_with_direction(ctx, aead, key, key_len, tag_len,
|
||||
evp_aead_open);
|
||||
}
|
||||
|
||||
int EVP_AEAD_CTX_init_with_direction(EVP_AEAD_CTX *ctx, const EVP_AEAD *aead,
|
||||
const uint8_t *key, size_t key_len,
|
||||
size_t tag_len,
|
||||
enum evp_aead_direction_t dir) {
|
||||
if (key_len != aead->key_len) {
|
||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_UNSUPPORTED_KEY_SIZE);
|
||||
ctx->aead = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
ctx->aead = aead;
|
||||
|
||||
int ok;
|
||||
if (aead->init) {
|
||||
ok = aead->init(ctx, key, key_len, tag_len);
|
||||
} else {
|
||||
ok = aead->init_with_direction(ctx, key, key_len, tag_len, dir);
|
||||
}
|
||||
|
||||
if (!ok) {
|
||||
ctx->aead = NULL;
|
||||
}
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
void EVP_AEAD_CTX_cleanup(EVP_AEAD_CTX *ctx) {
|
||||
if (ctx->aead == NULL) {
|
||||
return;
|
||||
}
|
||||
ctx->aead->cleanup(ctx);
|
||||
ctx->aead = NULL;
|
||||
}
|
||||
|
||||
/* check_alias returns 1 if |out| is compatible with |in| and 0 otherwise. If
|
||||
* |in| and |out| alias, we require that |in| == |out|. */
|
||||
static int check_alias(const uint8_t *in, size_t in_len, const uint8_t *out,
|
||||
size_t out_len) {
|
||||
if (!buffers_alias(in, in_len, out, out_len)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return in == out;
|
||||
}
|
||||
|
||||
int EVP_AEAD_CTX_seal(const EVP_AEAD_CTX *ctx, uint8_t *out, size_t *out_len,
|
||||
size_t max_out_len, const uint8_t *nonce,
|
||||
size_t nonce_len, const uint8_t *in, size_t in_len,
|
||||
const uint8_t *ad, size_t ad_len) {
|
||||
size_t possible_out_len = in_len + ctx->aead->overhead;
|
||||
|
||||
if (possible_out_len < in_len /* overflow */) {
|
||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE);
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (!check_alias(in, in_len, out, max_out_len)) {
|
||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_OUTPUT_ALIASES_INPUT);
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (ctx->aead->seal(ctx, out, out_len, max_out_len, nonce, nonce_len, in,
|
||||
in_len, ad, ad_len)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
error:
|
||||
/* In the event of an error, clear the output buffer so that a caller
|
||||
* that doesn't check the return value doesn't send raw data. */
|
||||
OPENSSL_memset(out, 0, max_out_len);
|
||||
*out_len = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int EVP_AEAD_CTX_open(const EVP_AEAD_CTX *ctx, uint8_t *out, size_t *out_len,
|
||||
size_t max_out_len, const uint8_t *nonce,
|
||||
size_t nonce_len, const uint8_t *in, size_t in_len,
|
||||
const uint8_t *ad, size_t ad_len) {
|
||||
if (!check_alias(in, in_len, out, max_out_len)) {
|
||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_OUTPUT_ALIASES_INPUT);
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (ctx->aead->open(ctx, out, out_len, max_out_len, nonce, nonce_len, in,
|
||||
in_len, ad, ad_len)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
error:
|
||||
/* In the event of an error, clear the output buffer so that a caller
|
||||
* that doesn't check the return value doesn't try and process bad
|
||||
* data. */
|
||||
OPENSSL_memset(out, 0, max_out_len);
|
||||
*out_len = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
const EVP_AEAD *EVP_AEAD_CTX_aead(const EVP_AEAD_CTX *ctx) { return ctx->aead; }
|
||||
|
||||
int EVP_AEAD_CTX_get_iv(const EVP_AEAD_CTX *ctx, const uint8_t **out_iv,
|
||||
size_t *out_len) {
|
||||
if (ctx->aead->get_iv == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return ctx->aead->get_iv(ctx, out_iv, out_len);
|
||||
}
|
||||
@@ -1,450 +0,0 @@
|
||||
/* Copyright (c) 2014, Google Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <openssl/aead.h>
|
||||
#include <openssl/crypto.h>
|
||||
#include <openssl/err.h>
|
||||
|
||||
#include "../internal.h"
|
||||
#include "../test/file_test.h"
|
||||
|
||||
|
||||
#if defined(OPENSSL_SMALL)
|
||||
const EVP_AEAD* EVP_aead_aes_128_gcm_siv(void) {
|
||||
return nullptr;
|
||||
}
|
||||
const EVP_AEAD* EVP_aead_aes_256_gcm_siv(void) {
|
||||
return nullptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
// This program tests an AEAD against a series of test vectors from a file,
|
||||
// using the FileTest format. As an example, here's a valid test case:
|
||||
//
|
||||
// KEY: 5a19f3173586b4c42f8412f4d5a786531b3231753e9e00998aec12fda8df10e4
|
||||
// NONCE: 978105dfce667bf4
|
||||
// IN: 6a4583908d
|
||||
// AD: b654574932
|
||||
// CT: 5294265a60
|
||||
// TAG: 1d45758621762e061368e68868e2f929
|
||||
|
||||
static bool TestAEAD(FileTest *t, void *arg) {
|
||||
const EVP_AEAD *aead = reinterpret_cast<const EVP_AEAD*>(arg);
|
||||
|
||||
std::vector<uint8_t> key, nonce, in, ad, ct, tag;
|
||||
if (!t->GetBytes(&key, "KEY") ||
|
||||
!t->GetBytes(&nonce, "NONCE") ||
|
||||
!t->GetBytes(&in, "IN") ||
|
||||
!t->GetBytes(&ad, "AD") ||
|
||||
!t->GetBytes(&ct, "CT") ||
|
||||
!t->GetBytes(&tag, "TAG")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bssl::ScopedEVP_AEAD_CTX ctx;
|
||||
if (!EVP_AEAD_CTX_init_with_direction(ctx.get(), aead, key.data(), key.size(),
|
||||
tag.size(), evp_aead_seal)) {
|
||||
t->PrintLine("Failed to init AEAD.");
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<uint8_t> out(in.size() + EVP_AEAD_max_overhead(aead));
|
||||
if (!t->HasAttribute("NO_SEAL")) {
|
||||
size_t out_len;
|
||||
if (!EVP_AEAD_CTX_seal(ctx.get(), out.data(), &out_len, out.size(),
|
||||
nonce.data(), nonce.size(), in.data(), in.size(),
|
||||
ad.data(), ad.size())) {
|
||||
t->PrintLine("Failed to run AEAD.");
|
||||
return false;
|
||||
}
|
||||
out.resize(out_len);
|
||||
|
||||
if (out.size() != ct.size() + tag.size()) {
|
||||
t->PrintLine("Bad output length: %u vs %u.", (unsigned)out_len,
|
||||
(unsigned)(ct.size() + tag.size()));
|
||||
return false;
|
||||
}
|
||||
if (!t->ExpectBytesEqual(ct.data(), ct.size(), out.data(), ct.size()) ||
|
||||
!t->ExpectBytesEqual(tag.data(), tag.size(), out.data() + ct.size(),
|
||||
tag.size())) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
out.resize(ct.size() + tag.size());
|
||||
OPENSSL_memcpy(out.data(), ct.data(), ct.size());
|
||||
OPENSSL_memcpy(out.data() + ct.size(), tag.data(), tag.size());
|
||||
}
|
||||
|
||||
// The "stateful" AEADs for implementing pre-AEAD cipher suites need to be
|
||||
// reset after each operation.
|
||||
ctx.Reset();
|
||||
if (!EVP_AEAD_CTX_init_with_direction(ctx.get(), aead, key.data(), key.size(),
|
||||
tag.size(), evp_aead_open)) {
|
||||
t->PrintLine("Failed to init AEAD.");
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<uint8_t> out2(out.size());
|
||||
size_t out2_len;
|
||||
int ret = EVP_AEAD_CTX_open(ctx.get(), out2.data(), &out2_len, out2.size(),
|
||||
nonce.data(), nonce.size(), out.data(),
|
||||
out.size(), ad.data(), ad.size());
|
||||
if (t->HasAttribute("FAILS")) {
|
||||
if (ret) {
|
||||
t->PrintLine("Decrypted bad data.");
|
||||
return false;
|
||||
}
|
||||
ERR_clear_error();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!ret) {
|
||||
t->PrintLine("Failed to decrypt.");
|
||||
return false;
|
||||
}
|
||||
out2.resize(out2_len);
|
||||
if (!t->ExpectBytesEqual(in.data(), in.size(), out2.data(), out2.size())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// The "stateful" AEADs for implementing pre-AEAD cipher suites need to be
|
||||
// reset after each operation.
|
||||
ctx.Reset();
|
||||
if (!EVP_AEAD_CTX_init_with_direction(ctx.get(), aead, key.data(), key.size(),
|
||||
tag.size(), evp_aead_open)) {
|
||||
t->PrintLine("Failed to init AEAD.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Garbage at the end isn't ignored.
|
||||
out.push_back(0);
|
||||
out2.resize(out.size());
|
||||
if (EVP_AEAD_CTX_open(ctx.get(), out2.data(), &out2_len, out2.size(),
|
||||
nonce.data(), nonce.size(), out.data(), out.size(),
|
||||
ad.data(), ad.size())) {
|
||||
t->PrintLine("Decrypted bad data with trailing garbage.");
|
||||
return false;
|
||||
}
|
||||
ERR_clear_error();
|
||||
|
||||
// The "stateful" AEADs for implementing pre-AEAD cipher suites need to be
|
||||
// reset after each operation.
|
||||
ctx.Reset();
|
||||
if (!EVP_AEAD_CTX_init_with_direction(ctx.get(), aead, key.data(), key.size(),
|
||||
tag.size(), evp_aead_open)) {
|
||||
t->PrintLine("Failed to init AEAD.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Verify integrity is checked.
|
||||
out[0] ^= 0x80;
|
||||
out.resize(out.size() - 1);
|
||||
out2.resize(out.size());
|
||||
if (EVP_AEAD_CTX_open(ctx.get(), out2.data(), &out2_len, out2.size(),
|
||||
nonce.data(), nonce.size(), out.data(), out.size(),
|
||||
ad.data(), ad.size())) {
|
||||
t->PrintLine("Decrypted bad data with corrupted byte.");
|
||||
return false;
|
||||
}
|
||||
ERR_clear_error();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static int TestCleanupAfterInitFailure(const EVP_AEAD *aead) {
|
||||
uint8_t key[EVP_AEAD_MAX_KEY_LENGTH];
|
||||
OPENSSL_memset(key, 0, sizeof(key));
|
||||
const size_t key_len = EVP_AEAD_key_length(aead);
|
||||
assert(sizeof(key) >= key_len);
|
||||
|
||||
EVP_AEAD_CTX ctx;
|
||||
if (EVP_AEAD_CTX_init(&ctx, aead, key, key_len,
|
||||
9999 /* a silly tag length to trigger an error */,
|
||||
NULL /* ENGINE */) != 0) {
|
||||
fprintf(stderr, "A silly tag length didn't trigger an error!\n");
|
||||
return 0;
|
||||
}
|
||||
ERR_clear_error();
|
||||
|
||||
/* Running a second, failed _init should not cause a memory leak. */
|
||||
if (EVP_AEAD_CTX_init(&ctx, aead, key, key_len,
|
||||
9999 /* a silly tag length to trigger an error */,
|
||||
NULL /* ENGINE */) != 0) {
|
||||
fprintf(stderr, "A silly tag length didn't trigger an error!\n");
|
||||
return 0;
|
||||
}
|
||||
ERR_clear_error();
|
||||
|
||||
/* Calling _cleanup on an |EVP_AEAD_CTX| after a failed _init should be a
|
||||
* no-op. */
|
||||
EVP_AEAD_CTX_cleanup(&ctx);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int TestTruncatedTags(const EVP_AEAD *aead) {
|
||||
uint8_t key[EVP_AEAD_MAX_KEY_LENGTH];
|
||||
OPENSSL_memset(key, 0, sizeof(key));
|
||||
const size_t key_len = EVP_AEAD_key_length(aead);
|
||||
assert(sizeof(key) >= key_len);
|
||||
|
||||
uint8_t nonce[EVP_AEAD_MAX_NONCE_LENGTH];
|
||||
OPENSSL_memset(nonce, 0, sizeof(nonce));
|
||||
const size_t nonce_len = EVP_AEAD_nonce_length(aead);
|
||||
assert(sizeof(nonce) >= nonce_len);
|
||||
|
||||
bssl::ScopedEVP_AEAD_CTX ctx;
|
||||
if (!EVP_AEAD_CTX_init(ctx.get(), aead, key, key_len, 1 /* one byte tag */,
|
||||
NULL /* ENGINE */)) {
|
||||
fprintf(stderr, "Couldn't initialise AEAD with truncated tag.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
const uint8_t plaintext[1] = {'A'};
|
||||
|
||||
uint8_t ciphertext[128];
|
||||
size_t ciphertext_len;
|
||||
constexpr uint8_t kSentinel = 42;
|
||||
OPENSSL_memset(ciphertext, kSentinel, sizeof(ciphertext));
|
||||
|
||||
if (!EVP_AEAD_CTX_seal(ctx.get(), ciphertext, &ciphertext_len,
|
||||
sizeof(ciphertext), nonce, nonce_len, plaintext,
|
||||
sizeof(plaintext), nullptr /* ad */, 0)) {
|
||||
fprintf(stderr, "Sealing with truncated tag didn't work.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (size_t i = ciphertext_len; i < sizeof(ciphertext); i++) {
|
||||
// Sealing must not write past where it said it did.
|
||||
if (ciphertext[i] != kSentinel) {
|
||||
fprintf(stderr, "Sealing wrote off the end of the buffer.\n");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
const size_t overhead_used = ciphertext_len - sizeof(plaintext);
|
||||
if (overhead_used != 1) {
|
||||
fprintf(stderr, "AEAD is probably ignoring request to truncate tags.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t plaintext2[sizeof(plaintext) + 16];
|
||||
OPENSSL_memset(plaintext2, kSentinel, sizeof(plaintext2));
|
||||
|
||||
size_t plaintext2_len;
|
||||
if (!EVP_AEAD_CTX_open(ctx.get(), plaintext2, &plaintext2_len,
|
||||
sizeof(plaintext2), nonce, nonce_len, ciphertext,
|
||||
ciphertext_len, nullptr /* ad */, 0)) {
|
||||
fprintf(stderr, "Opening with truncated tag didn't work.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (size_t i = plaintext2_len; i < sizeof(plaintext2); i++) {
|
||||
// Likewise, opening should also stay within bounds.
|
||||
if (plaintext2[i] != kSentinel) {
|
||||
fprintf(stderr, "Opening wrote off the end of the buffer.\n");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (plaintext2_len != sizeof(plaintext) ||
|
||||
OPENSSL_memcmp(plaintext2, plaintext, sizeof(plaintext)) != 0) {
|
||||
fprintf(stderr, "Opening with truncated tag gave wrong result.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static bool TestWithAliasedBuffers(const EVP_AEAD *aead) {
|
||||
const size_t key_len = EVP_AEAD_key_length(aead);
|
||||
const size_t nonce_len = EVP_AEAD_nonce_length(aead);
|
||||
const size_t max_overhead = EVP_AEAD_max_overhead(aead);
|
||||
|
||||
std::vector<uint8_t> key(key_len, 'a');
|
||||
bssl::ScopedEVP_AEAD_CTX ctx;
|
||||
if (!EVP_AEAD_CTX_init(ctx.get(), aead, key.data(), key_len,
|
||||
EVP_AEAD_DEFAULT_TAG_LENGTH, nullptr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
static const uint8_t kPlaintext[260] =
|
||||
"testing123456testing123456testing123456testing123456testing123456testing"
|
||||
"123456testing123456testing123456testing123456testing123456testing123456t"
|
||||
"esting123456testing123456testing123456testing123456testing123456testing1"
|
||||
"23456testing123456testing123456testing12345";
|
||||
const std::vector<size_t> offsets = {
|
||||
0, 1, 2, 8, 15, 16, 17, 31, 32, 33, 63,
|
||||
64, 65, 95, 96, 97, 127, 128, 129, 255, 256, 257,
|
||||
};
|
||||
|
||||
std::vector<uint8_t> nonce(nonce_len, 'b');
|
||||
std::vector<uint8_t> valid_encryption(sizeof(kPlaintext) + max_overhead);
|
||||
size_t valid_encryption_len;
|
||||
if (!EVP_AEAD_CTX_seal(
|
||||
ctx.get(), valid_encryption.data(), &valid_encryption_len,
|
||||
sizeof(kPlaintext) + max_overhead, nonce.data(), nonce_len,
|
||||
kPlaintext, sizeof(kPlaintext), nullptr, 0)) {
|
||||
fprintf(stderr, "EVP_AEAD_CTX_seal failed with disjoint buffers.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Test with out != in which we expect to fail.
|
||||
std::vector<uint8_t> buffer(2 + valid_encryption_len);
|
||||
uint8_t *in = buffer.data() + 1;
|
||||
uint8_t *out1 = buffer.data();
|
||||
uint8_t *out2 = buffer.data() + 2;
|
||||
|
||||
OPENSSL_memcpy(in, kPlaintext, sizeof(kPlaintext));
|
||||
size_t out_len;
|
||||
if (EVP_AEAD_CTX_seal(ctx.get(), out1, &out_len,
|
||||
sizeof(kPlaintext) + max_overhead, nonce.data(),
|
||||
nonce_len, in, sizeof(kPlaintext), nullptr, 0) ||
|
||||
EVP_AEAD_CTX_seal(ctx.get(), out2, &out_len,
|
||||
sizeof(kPlaintext) + max_overhead, nonce.data(),
|
||||
nonce_len, in, sizeof(kPlaintext), nullptr, 0)) {
|
||||
fprintf(stderr, "EVP_AEAD_CTX_seal unexpectedly succeeded.\n");
|
||||
return false;
|
||||
}
|
||||
ERR_clear_error();
|
||||
|
||||
OPENSSL_memcpy(in, valid_encryption.data(), valid_encryption_len);
|
||||
if (EVP_AEAD_CTX_open(ctx.get(), out1, &out_len, valid_encryption_len,
|
||||
nonce.data(), nonce_len, in, valid_encryption_len,
|
||||
nullptr, 0) ||
|
||||
EVP_AEAD_CTX_open(ctx.get(), out2, &out_len, valid_encryption_len,
|
||||
nonce.data(), nonce_len, in, valid_encryption_len,
|
||||
nullptr, 0)) {
|
||||
fprintf(stderr, "EVP_AEAD_CTX_open unexpectedly succeeded.\n");
|
||||
return false;
|
||||
}
|
||||
ERR_clear_error();
|
||||
|
||||
// Test with out == in, which we expect to work.
|
||||
OPENSSL_memcpy(in, kPlaintext, sizeof(kPlaintext));
|
||||
|
||||
if (!EVP_AEAD_CTX_seal(ctx.get(), in, &out_len,
|
||||
sizeof(kPlaintext) + max_overhead, nonce.data(),
|
||||
nonce_len, in, sizeof(kPlaintext), nullptr, 0)) {
|
||||
fprintf(stderr, "EVP_AEAD_CTX_seal failed in-place.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (out_len != valid_encryption_len ||
|
||||
OPENSSL_memcmp(in, valid_encryption.data(), out_len) != 0) {
|
||||
fprintf(stderr, "EVP_AEAD_CTX_seal produced bad output in-place.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
OPENSSL_memcpy(in, valid_encryption.data(), valid_encryption_len);
|
||||
if (!EVP_AEAD_CTX_open(ctx.get(), in, &out_len, valid_encryption_len,
|
||||
nonce.data(), nonce_len, in, valid_encryption_len,
|
||||
nullptr, 0)) {
|
||||
fprintf(stderr, "EVP_AEAD_CTX_open failed in-place.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (out_len != sizeof(kPlaintext) ||
|
||||
OPENSSL_memcmp(in, kPlaintext, out_len) != 0) {
|
||||
fprintf(stderr, "EVP_AEAD_CTX_open produced bad output in-place.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
struct KnownAEAD {
|
||||
const char name[40];
|
||||
const EVP_AEAD *(*func)(void);
|
||||
// limited_implementation indicates that tests that assume a generic AEAD
|
||||
// interface should not be performed. For example, the key-wrap AEADs only
|
||||
// handle inputs that are a multiple of eight bytes in length and the
|
||||
// SSLv3/TLS AEADs have the concept of “direction”.
|
||||
bool limited_implementation;
|
||||
// truncated_tags is true if the AEAD supports truncating tags to arbitrary
|
||||
// lengths.
|
||||
bool truncated_tags;
|
||||
};
|
||||
|
||||
static const struct KnownAEAD kAEADs[] = {
|
||||
{ "aes-128-gcm", EVP_aead_aes_128_gcm, false, true },
|
||||
{ "aes-256-gcm", EVP_aead_aes_256_gcm, false, true },
|
||||
{ "aes-128-gcm-siv", EVP_aead_aes_128_gcm_siv, false, false },
|
||||
{ "aes-256-gcm-siv", EVP_aead_aes_256_gcm_siv, false, false },
|
||||
{ "chacha20-poly1305", EVP_aead_chacha20_poly1305, false, true },
|
||||
{ "aes-128-cbc-sha1-tls", EVP_aead_aes_128_cbc_sha1_tls, true, false },
|
||||
{ "aes-128-cbc-sha1-tls-implicit-iv", EVP_aead_aes_128_cbc_sha1_tls_implicit_iv, true, false },
|
||||
{ "aes-128-cbc-sha256-tls", EVP_aead_aes_128_cbc_sha256_tls, true, false },
|
||||
{ "aes-256-cbc-sha1-tls", EVP_aead_aes_256_cbc_sha1_tls, true, false },
|
||||
{ "aes-256-cbc-sha1-tls-implicit-iv", EVP_aead_aes_256_cbc_sha1_tls_implicit_iv, true, false },
|
||||
{ "aes-256-cbc-sha256-tls", EVP_aead_aes_256_cbc_sha256_tls, true, false },
|
||||
{ "aes-256-cbc-sha384-tls", EVP_aead_aes_256_cbc_sha384_tls, true, false },
|
||||
{ "des-ede3-cbc-sha1-tls", EVP_aead_des_ede3_cbc_sha1_tls, true, false },
|
||||
{ "des-ede3-cbc-sha1-tls-implicit-iv", EVP_aead_des_ede3_cbc_sha1_tls_implicit_iv, true, false },
|
||||
{ "aes-128-cbc-sha1-ssl3", EVP_aead_aes_128_cbc_sha1_ssl3, true, false },
|
||||
{ "aes-256-cbc-sha1-ssl3", EVP_aead_aes_256_cbc_sha1_ssl3, true, false },
|
||||
{ "des-ede3-cbc-sha1-ssl3", EVP_aead_des_ede3_cbc_sha1_ssl3, true, false },
|
||||
{ "aes-128-ctr-hmac-sha256", EVP_aead_aes_128_ctr_hmac_sha256, false, true },
|
||||
{ "aes-256-ctr-hmac-sha256", EVP_aead_aes_256_ctr_hmac_sha256, false, true },
|
||||
{ "", NULL, false, false },
|
||||
};
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
CRYPTO_library_init();
|
||||
|
||||
if (argc != 3) {
|
||||
fprintf(stderr, "%s <aead> <test file.txt>\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
const struct KnownAEAD *known_aead;
|
||||
for (unsigned i = 0;; i++) {
|
||||
known_aead = &kAEADs[i];
|
||||
if (known_aead->func == NULL) {
|
||||
fprintf(stderr, "Unknown AEAD: %s\n", argv[1]);
|
||||
return 2;
|
||||
}
|
||||
if (strcmp(known_aead->name, argv[1]) == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const EVP_AEAD *const aead = known_aead->func();
|
||||
if (aead == NULL) {
|
||||
// AEAD is not compiled in this configuration.
|
||||
printf("PASS\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!TestCleanupAfterInitFailure(aead)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (known_aead->truncated_tags && !TestTruncatedTags(aead)) {
|
||||
fprintf(stderr, "Truncated tags test failed for %s.\n", known_aead->name);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!known_aead->limited_implementation && !TestWithAliasedBuffers(aead)) {
|
||||
fprintf(stderr, "Aliased buffers test failed for %s.\n", known_aead->name);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return FileTestMain(TestAEAD, const_cast<EVP_AEAD*>(aead), argv[2]);
|
||||
}
|
||||
@@ -1,295 +0,0 @@
|
||||
/*
|
||||
* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
|
||||
* project.
|
||||
*/
|
||||
/* ====================================================================
|
||||
* Copyright (c) 2015 The OpenSSL Project. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. All advertising materials mentioning features or use of this
|
||||
* software must display the following acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
|
||||
*
|
||||
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
|
||||
* endorse or promote products derived from this software without
|
||||
* prior written permission. For written permission, please contact
|
||||
* licensing@OpenSSL.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "OpenSSL"
|
||||
* nor may "OpenSSL" appear in their names without prior written
|
||||
* permission of the OpenSSL Project.
|
||||
*
|
||||
* 6. Redistributions of any form whatsoever must retain the following
|
||||
* acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
|
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <openssl/cipher.h>
|
||||
#include <openssl/crypto.h>
|
||||
#include <openssl/err.h>
|
||||
|
||||
#include "../test/file_test.h"
|
||||
|
||||
|
||||
static const EVP_CIPHER *GetCipher(const std::string &name) {
|
||||
if (name == "DES-CBC") {
|
||||
return EVP_des_cbc();
|
||||
} else if (name == "DES-ECB") {
|
||||
return EVP_des_ecb();
|
||||
} else if (name == "DES-EDE") {
|
||||
return EVP_des_ede();
|
||||
} else if (name == "DES-EDE-CBC") {
|
||||
return EVP_des_ede_cbc();
|
||||
} else if (name == "DES-EDE3-CBC") {
|
||||
return EVP_des_ede3_cbc();
|
||||
} else if (name == "RC4") {
|
||||
return EVP_rc4();
|
||||
} else if (name == "AES-128-ECB") {
|
||||
return EVP_aes_128_ecb();
|
||||
} else if (name == "AES-256-ECB") {
|
||||
return EVP_aes_256_ecb();
|
||||
} else if (name == "AES-128-CBC") {
|
||||
return EVP_aes_128_cbc();
|
||||
} else if (name == "AES-128-GCM") {
|
||||
return EVP_aes_128_gcm();
|
||||
} else if (name == "AES-128-OFB") {
|
||||
return EVP_aes_128_ofb();
|
||||
} else if (name == "AES-192-CBC") {
|
||||
return EVP_aes_192_cbc();
|
||||
} else if (name == "AES-192-ECB") {
|
||||
return EVP_aes_192_ecb();
|
||||
} else if (name == "AES-256-CBC") {
|
||||
return EVP_aes_256_cbc();
|
||||
} else if (name == "AES-128-CTR") {
|
||||
return EVP_aes_128_ctr();
|
||||
} else if (name == "AES-256-CTR") {
|
||||
return EVP_aes_256_ctr();
|
||||
} else if (name == "AES-256-GCM") {
|
||||
return EVP_aes_256_gcm();
|
||||
} else if (name == "AES-256-OFB") {
|
||||
return EVP_aes_256_ofb();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static bool TestOperation(FileTest *t,
|
||||
const EVP_CIPHER *cipher,
|
||||
bool encrypt,
|
||||
size_t chunk_size,
|
||||
const std::vector<uint8_t> &key,
|
||||
const std::vector<uint8_t> &iv,
|
||||
const std::vector<uint8_t> &plaintext,
|
||||
const std::vector<uint8_t> &ciphertext,
|
||||
const std::vector<uint8_t> &aad,
|
||||
const std::vector<uint8_t> &tag) {
|
||||
const std::vector<uint8_t> *in, *out;
|
||||
if (encrypt) {
|
||||
in = &plaintext;
|
||||
out = &ciphertext;
|
||||
} else {
|
||||
in = &ciphertext;
|
||||
out = &plaintext;
|
||||
}
|
||||
|
||||
bool is_aead = EVP_CIPHER_mode(cipher) == EVP_CIPH_GCM_MODE;
|
||||
|
||||
bssl::ScopedEVP_CIPHER_CTX ctx;
|
||||
if (!EVP_CipherInit_ex(ctx.get(), cipher, nullptr, nullptr, nullptr,
|
||||
encrypt ? 1 : 0)) {
|
||||
return false;
|
||||
}
|
||||
if (t->HasAttribute("IV")) {
|
||||
if (is_aead) {
|
||||
if (!EVP_CIPHER_CTX_ctrl(ctx.get(), EVP_CTRL_GCM_SET_IVLEN,
|
||||
iv.size(), 0)) {
|
||||
return false;
|
||||
}
|
||||
} else if (iv.size() != EVP_CIPHER_CTX_iv_length(ctx.get())) {
|
||||
t->PrintLine("Bad IV length.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (is_aead && !encrypt &&
|
||||
!EVP_CIPHER_CTX_ctrl(ctx.get(), EVP_CTRL_GCM_SET_TAG, tag.size(),
|
||||
const_cast<uint8_t*>(tag.data()))) {
|
||||
return false;
|
||||
}
|
||||
// The ciphers are run with no padding. For each of the ciphers we test, the
|
||||
// output size matches the input size.
|
||||
std::vector<uint8_t> result(in->size());
|
||||
if (in->size() != out->size()) {
|
||||
t->PrintLine("Input/output size mismatch (%u vs %u).", (unsigned)in->size(),
|
||||
(unsigned)out->size());
|
||||
return false;
|
||||
}
|
||||
// Note: the deprecated |EVP_CIPHER|-based AES-GCM API is sensitive to whether
|
||||
// parameters are NULL, so it is important to skip the |in| and |aad|
|
||||
// |EVP_CipherUpdate| calls when empty.
|
||||
int unused, result_len1 = 0, result_len2;
|
||||
if (!EVP_CIPHER_CTX_set_key_length(ctx.get(), key.size()) ||
|
||||
!EVP_CipherInit_ex(ctx.get(), nullptr, nullptr, key.data(), iv.data(),
|
||||
-1) ||
|
||||
(!aad.empty() &&
|
||||
!EVP_CipherUpdate(ctx.get(), nullptr, &unused, aad.data(),
|
||||
aad.size())) ||
|
||||
!EVP_CIPHER_CTX_set_padding(ctx.get(), 0)) {
|
||||
t->PrintLine("Operation failed.");
|
||||
return false;
|
||||
}
|
||||
if (chunk_size != 0) {
|
||||
for (size_t i = 0; i < in->size();) {
|
||||
size_t todo = chunk_size;
|
||||
if (i + todo > in->size()) {
|
||||
todo = in->size() - i;
|
||||
}
|
||||
|
||||
int len;
|
||||
if (!EVP_CipherUpdate(ctx.get(), result.data() + result_len1, &len,
|
||||
in->data() + i, todo)) {
|
||||
t->PrintLine("Operation failed.");
|
||||
return false;
|
||||
}
|
||||
result_len1 += len;
|
||||
i += todo;
|
||||
}
|
||||
} else if (!in->empty() &&
|
||||
!EVP_CipherUpdate(ctx.get(), result.data(), &result_len1,
|
||||
in->data(), in->size())) {
|
||||
t->PrintLine("Operation failed.");
|
||||
return false;
|
||||
}
|
||||
if (!EVP_CipherFinal_ex(ctx.get(), result.data() + result_len1,
|
||||
&result_len2)) {
|
||||
t->PrintLine("Operation failed.");
|
||||
return false;
|
||||
}
|
||||
result.resize(result_len1 + result_len2);
|
||||
if (!t->ExpectBytesEqual(out->data(), out->size(), result.data(),
|
||||
result.size())) {
|
||||
return false;
|
||||
}
|
||||
if (encrypt && is_aead) {
|
||||
uint8_t rtag[16];
|
||||
if (tag.size() > sizeof(rtag)) {
|
||||
t->PrintLine("Bad tag length.");
|
||||
return false;
|
||||
}
|
||||
if (!EVP_CIPHER_CTX_ctrl(ctx.get(), EVP_CTRL_GCM_GET_TAG, tag.size(),
|
||||
rtag) ||
|
||||
!t->ExpectBytesEqual(tag.data(), tag.size(), rtag,
|
||||
tag.size())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool TestCipher(FileTest *t, void *arg) {
|
||||
std::string cipher_str;
|
||||
if (!t->GetAttribute(&cipher_str, "Cipher")) {
|
||||
return false;
|
||||
}
|
||||
const EVP_CIPHER *cipher = GetCipher(cipher_str);
|
||||
if (cipher == nullptr) {
|
||||
t->PrintLine("Unknown cipher: '%s'.", cipher_str.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<uint8_t> key, iv, plaintext, ciphertext, aad, tag;
|
||||
if (!t->GetBytes(&key, "Key") ||
|
||||
!t->GetBytes(&plaintext, "Plaintext") ||
|
||||
!t->GetBytes(&ciphertext, "Ciphertext")) {
|
||||
return false;
|
||||
}
|
||||
if (EVP_CIPHER_iv_length(cipher) > 0 &&
|
||||
!t->GetBytes(&iv, "IV")) {
|
||||
return false;
|
||||
}
|
||||
if (EVP_CIPHER_mode(cipher) == EVP_CIPH_GCM_MODE) {
|
||||
if (!t->GetBytes(&aad, "AAD") ||
|
||||
!t->GetBytes(&tag, "Tag")) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
enum {
|
||||
kEncrypt,
|
||||
kDecrypt,
|
||||
kBoth,
|
||||
} operation = kBoth;
|
||||
if (t->HasAttribute("Operation")) {
|
||||
const std::string &str = t->GetAttributeOrDie("Operation");
|
||||
if (str == "ENCRYPT") {
|
||||
operation = kEncrypt;
|
||||
} else if (str == "DECRYPT") {
|
||||
operation = kDecrypt;
|
||||
} else {
|
||||
t->PrintLine("Unknown operation: '%s'.", str.c_str());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
const std::vector<size_t> chunk_sizes = {0, 1, 2, 5, 7, 8, 9, 15, 16,
|
||||
17, 31, 32, 33, 63, 64, 65, 512};
|
||||
|
||||
for (size_t chunk_size : chunk_sizes) {
|
||||
// By default, both directions are run, unless overridden by the operation.
|
||||
if (operation != kDecrypt &&
|
||||
!TestOperation(t, cipher, true /* encrypt */, chunk_size, key, iv,
|
||||
plaintext, ciphertext, aad, tag)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (operation != kEncrypt &&
|
||||
!TestOperation(t, cipher, false /* decrypt */, chunk_size, key, iv,
|
||||
plaintext, ciphertext, aad, tag)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
CRYPTO_library_init();
|
||||
|
||||
if (argc != 2) {
|
||||
fprintf(stderr, "%s <test file>\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return FileTestMain(TestCipher, nullptr, argv[1]);
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,276 +0,0 @@
|
||||
/* Copyright (c) 2014, Google Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
|
||||
|
||||
#include <openssl/aead.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl/chacha.h>
|
||||
#include <openssl/cipher.h>
|
||||
#include <openssl/cpu.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.h>
|
||||
#include <openssl/poly1305.h>
|
||||
|
||||
#include "internal.h"
|
||||
#include "../internal.h"
|
||||
|
||||
|
||||
#define POLY1305_TAG_LEN 16
|
||||
|
||||
struct aead_chacha20_poly1305_ctx {
|
||||
unsigned char key[32];
|
||||
unsigned char tag_len;
|
||||
};
|
||||
|
||||
#if defined(OPENSSL_X86_64) && !defined(OPENSSL_NO_ASM) && \
|
||||
!defined(OPENSSL_WINDOWS)
|
||||
static int asm_capable(void) {
|
||||
const int sse41_capable = (OPENSSL_ia32cap_P[1] & (1 << 19)) != 0;
|
||||
return sse41_capable;
|
||||
}
|
||||
|
||||
// chacha20_poly1305_open is defined in chacha20_poly1305_x86_64.pl. It
|
||||
// decrypts |plaintext_len| bytes from |ciphertext| and writes them to
|
||||
// |out_plaintext|. On entry, |aead_data| must contain the final 48 bytes of
|
||||
// the initial ChaCha20 block, i.e. the key, followed by four zeros, followed
|
||||
// by the nonce. On exit, it will contain the calculated tag value, which the
|
||||
// caller must check.
|
||||
extern void chacha20_poly1305_open(uint8_t *out_plaintext,
|
||||
const uint8_t *ciphertext,
|
||||
size_t plaintext_len, const uint8_t *ad,
|
||||
size_t ad_len, uint8_t *aead_data);
|
||||
|
||||
// chacha20_poly1305_open is defined in chacha20_poly1305_x86_64.pl. It
|
||||
// encrypts |plaintext_len| bytes from |plaintext| and writes them to
|
||||
// |out_ciphertext|. On entry, |aead_data| must contain the final 48 bytes of
|
||||
// the initial ChaCha20 block, i.e. the key, followed by four zeros, followed
|
||||
// by the nonce. On exit, it will contain the calculated tag value, which the
|
||||
// caller must append to the ciphertext.
|
||||
extern void chacha20_poly1305_seal(uint8_t *out_ciphertext,
|
||||
const uint8_t *plaintext,
|
||||
size_t plaintext_len, const uint8_t *ad,
|
||||
size_t ad_len, uint8_t *aead_data);
|
||||
#else
|
||||
static int asm_capable(void) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void chacha20_poly1305_open(uint8_t *out_plaintext,
|
||||
const uint8_t *ciphertext,
|
||||
size_t plaintext_len, const uint8_t *ad,
|
||||
size_t ad_len, uint8_t *aead_data) {}
|
||||
|
||||
static void chacha20_poly1305_seal(uint8_t *out_ciphertext,
|
||||
const uint8_t *plaintext,
|
||||
size_t plaintext_len, const uint8_t *ad,
|
||||
size_t ad_len, uint8_t *aead_data) {}
|
||||
#endif
|
||||
|
||||
static int aead_chacha20_poly1305_init(EVP_AEAD_CTX *ctx, const uint8_t *key,
|
||||
size_t key_len, size_t tag_len) {
|
||||
struct aead_chacha20_poly1305_ctx *c20_ctx;
|
||||
|
||||
if (tag_len == 0) {
|
||||
tag_len = POLY1305_TAG_LEN;
|
||||
}
|
||||
|
||||
if (tag_len > POLY1305_TAG_LEN) {
|
||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (key_len != sizeof(c20_ctx->key)) {
|
||||
return 0; /* internal error - EVP_AEAD_CTX_init should catch this. */
|
||||
}
|
||||
|
||||
c20_ctx = OPENSSL_malloc(sizeof(struct aead_chacha20_poly1305_ctx));
|
||||
if (c20_ctx == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
OPENSSL_memcpy(c20_ctx->key, key, key_len);
|
||||
c20_ctx->tag_len = tag_len;
|
||||
ctx->aead_state = c20_ctx;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void aead_chacha20_poly1305_cleanup(EVP_AEAD_CTX *ctx) {
|
||||
struct aead_chacha20_poly1305_ctx *c20_ctx = ctx->aead_state;
|
||||
OPENSSL_cleanse(c20_ctx->key, sizeof(c20_ctx->key));
|
||||
OPENSSL_free(c20_ctx);
|
||||
}
|
||||
|
||||
static void poly1305_update_length(poly1305_state *poly1305, size_t data_len) {
|
||||
uint8_t length_bytes[8];
|
||||
|
||||
for (unsigned i = 0; i < sizeof(length_bytes); i++) {
|
||||
length_bytes[i] = data_len;
|
||||
data_len >>= 8;
|
||||
}
|
||||
|
||||
CRYPTO_poly1305_update(poly1305, length_bytes, sizeof(length_bytes));
|
||||
}
|
||||
|
||||
static void poly1305_update_padded_16(poly1305_state *poly1305,
|
||||
const uint8_t *data, size_t data_len) {
|
||||
static const uint8_t padding[16] = { 0 }; /* Padding is all zeros. */
|
||||
|
||||
CRYPTO_poly1305_update(poly1305, data, data_len);
|
||||
if (data_len % 16 != 0) {
|
||||
CRYPTO_poly1305_update(poly1305, padding,
|
||||
sizeof(padding) - (data_len % 16));
|
||||
}
|
||||
}
|
||||
|
||||
/* calc_tag fills |tag| with the authentication tag for the given inputs. */
|
||||
static void calc_tag(uint8_t tag[POLY1305_TAG_LEN],
|
||||
const struct aead_chacha20_poly1305_ctx *c20_ctx,
|
||||
const uint8_t nonce[12], const uint8_t *ad, size_t ad_len,
|
||||
const uint8_t *ciphertext, size_t ciphertext_len) {
|
||||
alignas(16) uint8_t poly1305_key[32];
|
||||
OPENSSL_memset(poly1305_key, 0, sizeof(poly1305_key));
|
||||
CRYPTO_chacha_20(poly1305_key, poly1305_key, sizeof(poly1305_key),
|
||||
c20_ctx->key, nonce, 0);
|
||||
|
||||
poly1305_state ctx;
|
||||
CRYPTO_poly1305_init(&ctx, poly1305_key);
|
||||
poly1305_update_padded_16(&ctx, ad, ad_len);
|
||||
poly1305_update_padded_16(&ctx, ciphertext, ciphertext_len);
|
||||
poly1305_update_length(&ctx, ad_len);
|
||||
poly1305_update_length(&ctx, ciphertext_len);
|
||||
CRYPTO_poly1305_finish(&ctx, tag);
|
||||
}
|
||||
|
||||
static int aead_chacha20_poly1305_seal(const EVP_AEAD_CTX *ctx, uint8_t *out,
|
||||
size_t *out_len, size_t max_out_len,
|
||||
const uint8_t *nonce, size_t nonce_len,
|
||||
const uint8_t *in, size_t in_len,
|
||||
const uint8_t *ad, size_t ad_len) {
|
||||
const struct aead_chacha20_poly1305_ctx *c20_ctx = ctx->aead_state;
|
||||
const uint64_t in_len_64 = in_len;
|
||||
|
||||
if (nonce_len != 12) {
|
||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_UNSUPPORTED_NONCE_SIZE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* |CRYPTO_chacha_20| uses a 32-bit block counter. Therefore we disallow
|
||||
* individual operations that work on more than 256GB at a time.
|
||||
* |in_len_64| is needed because, on 32-bit platforms, size_t is only
|
||||
* 32-bits and this produces a warning because it's always false.
|
||||
* Casting to uint64_t inside the conditional is not sufficient to stop
|
||||
* the warning. */
|
||||
if (in_len_64 >= (UINT64_C(1) << 32) * 64 - 64) {
|
||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (in_len + c20_ctx->tag_len < in_len) {
|
||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (max_out_len < in_len + c20_ctx->tag_len) {
|
||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BUFFER_TOO_SMALL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
alignas(16) uint8_t tag[48];
|
||||
|
||||
if (asm_capable()) {
|
||||
OPENSSL_memcpy(tag, c20_ctx->key, 32);
|
||||
OPENSSL_memset(tag + 32, 0, 4);
|
||||
OPENSSL_memcpy(tag + 32 + 4, nonce, 12);
|
||||
chacha20_poly1305_seal(out, in, in_len, ad, ad_len, tag);
|
||||
} else {
|
||||
CRYPTO_chacha_20(out, in, in_len, c20_ctx->key, nonce, 1);
|
||||
calc_tag(tag, c20_ctx, nonce, ad, ad_len, out, in_len);
|
||||
}
|
||||
|
||||
OPENSSL_memcpy(out + in_len, tag, c20_ctx->tag_len);
|
||||
*out_len = in_len + c20_ctx->tag_len;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int aead_chacha20_poly1305_open(const EVP_AEAD_CTX *ctx, uint8_t *out,
|
||||
size_t *out_len, size_t max_out_len,
|
||||
const uint8_t *nonce, size_t nonce_len,
|
||||
const uint8_t *in, size_t in_len,
|
||||
const uint8_t *ad, size_t ad_len) {
|
||||
const struct aead_chacha20_poly1305_ctx *c20_ctx = ctx->aead_state;
|
||||
size_t plaintext_len;
|
||||
const uint64_t in_len_64 = in_len;
|
||||
|
||||
if (nonce_len != 12) {
|
||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_UNSUPPORTED_NONCE_SIZE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (in_len < c20_ctx->tag_len) {
|
||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* |CRYPTO_chacha_20| uses a 32-bit block counter. Therefore we disallow
|
||||
* individual operations that work on more than 256GB at a time.
|
||||
* |in_len_64| is needed because, on 32-bit platforms, size_t is only
|
||||
* 32-bits and this produces a warning because it's always false.
|
||||
* Casting to uint64_t inside the conditional is not sufficient to stop
|
||||
* the warning. */
|
||||
if (in_len_64 >= (UINT64_C(1) << 32) * 64 - 64) {
|
||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
plaintext_len = in_len - c20_ctx->tag_len;
|
||||
alignas(16) uint8_t tag[48];
|
||||
|
||||
if (asm_capable()) {
|
||||
OPENSSL_memcpy(tag, c20_ctx->key, 32);
|
||||
OPENSSL_memset(tag + 32, 0, 4);
|
||||
OPENSSL_memcpy(tag + 32 + 4, nonce, 12);
|
||||
chacha20_poly1305_open(out, in, plaintext_len, ad, ad_len, tag);
|
||||
} else {
|
||||
calc_tag(tag, c20_ctx, nonce, ad, ad_len, in, plaintext_len);
|
||||
CRYPTO_chacha_20(out, in, plaintext_len, c20_ctx->key, nonce, 1);
|
||||
}
|
||||
|
||||
if (CRYPTO_memcmp(tag, in + plaintext_len, c20_ctx->tag_len) != 0) {
|
||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT);
|
||||
return 0;
|
||||
}
|
||||
|
||||
*out_len = plaintext_len;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const EVP_AEAD aead_chacha20_poly1305 = {
|
||||
32, /* key len */
|
||||
12, /* nonce len */
|
||||
POLY1305_TAG_LEN, /* overhead */
|
||||
POLY1305_TAG_LEN, /* max tag length */
|
||||
aead_chacha20_poly1305_init,
|
||||
NULL, /* init_with_direction */
|
||||
aead_chacha20_poly1305_cleanup,
|
||||
aead_chacha20_poly1305_seal,
|
||||
aead_chacha20_poly1305_open,
|
||||
NULL, /* get_iv */
|
||||
};
|
||||
|
||||
const EVP_AEAD *EVP_aead_chacha20_poly1305(void) {
|
||||
return &aead_chacha20_poly1305;
|
||||
}
|
||||
@@ -1,404 +0,0 @@
|
||||
/* Copyright (c) 2014, Google Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
|
||||
|
||||
#include <assert.h>
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl/aead.h>
|
||||
#include <openssl/cipher.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/hmac.h>
|
||||
#include <openssl/md5.h>
|
||||
#include <openssl/mem.h>
|
||||
#include <openssl/sha.h>
|
||||
|
||||
#include "internal.h"
|
||||
#include "../internal.h"
|
||||
|
||||
|
||||
typedef struct {
|
||||
EVP_CIPHER_CTX cipher_ctx;
|
||||
EVP_MD_CTX md_ctx;
|
||||
} AEAD_SSL3_CTX;
|
||||
|
||||
static int ssl3_mac(AEAD_SSL3_CTX *ssl3_ctx, uint8_t *out, unsigned *out_len,
|
||||
const uint8_t *ad, size_t ad_len, const uint8_t *in,
|
||||
size_t in_len) {
|
||||
size_t md_size = EVP_MD_CTX_size(&ssl3_ctx->md_ctx);
|
||||
size_t pad_len = (md_size == 20) ? 40 : 48;
|
||||
|
||||
/* To allow for CBC mode which changes cipher length, |ad| doesn't include the
|
||||
* length for legacy ciphers. */
|
||||
uint8_t ad_extra[2];
|
||||
ad_extra[0] = (uint8_t)(in_len >> 8);
|
||||
ad_extra[1] = (uint8_t)(in_len & 0xff);
|
||||
|
||||
EVP_MD_CTX md_ctx;
|
||||
EVP_MD_CTX_init(&md_ctx);
|
||||
|
||||
uint8_t pad[48];
|
||||
uint8_t tmp[EVP_MAX_MD_SIZE];
|
||||
OPENSSL_memset(pad, 0x36, pad_len);
|
||||
if (!EVP_MD_CTX_copy_ex(&md_ctx, &ssl3_ctx->md_ctx) ||
|
||||
!EVP_DigestUpdate(&md_ctx, pad, pad_len) ||
|
||||
!EVP_DigestUpdate(&md_ctx, ad, ad_len) ||
|
||||
!EVP_DigestUpdate(&md_ctx, ad_extra, sizeof(ad_extra)) ||
|
||||
!EVP_DigestUpdate(&md_ctx, in, in_len) ||
|
||||
!EVP_DigestFinal_ex(&md_ctx, tmp, NULL)) {
|
||||
EVP_MD_CTX_cleanup(&md_ctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
OPENSSL_memset(pad, 0x5c, pad_len);
|
||||
if (!EVP_MD_CTX_copy_ex(&md_ctx, &ssl3_ctx->md_ctx) ||
|
||||
!EVP_DigestUpdate(&md_ctx, pad, pad_len) ||
|
||||
!EVP_DigestUpdate(&md_ctx, tmp, md_size) ||
|
||||
!EVP_DigestFinal_ex(&md_ctx, out, out_len)) {
|
||||
EVP_MD_CTX_cleanup(&md_ctx);
|
||||
return 0;
|
||||
}
|
||||
EVP_MD_CTX_cleanup(&md_ctx);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void aead_ssl3_cleanup(EVP_AEAD_CTX *ctx) {
|
||||
AEAD_SSL3_CTX *ssl3_ctx = (AEAD_SSL3_CTX *)ctx->aead_state;
|
||||
EVP_CIPHER_CTX_cleanup(&ssl3_ctx->cipher_ctx);
|
||||
EVP_MD_CTX_cleanup(&ssl3_ctx->md_ctx);
|
||||
OPENSSL_free(ssl3_ctx);
|
||||
ctx->aead_state = NULL;
|
||||
}
|
||||
|
||||
static int aead_ssl3_init(EVP_AEAD_CTX *ctx, const uint8_t *key, size_t key_len,
|
||||
size_t tag_len, enum evp_aead_direction_t dir,
|
||||
const EVP_CIPHER *cipher, const EVP_MD *md) {
|
||||
if (tag_len != EVP_AEAD_DEFAULT_TAG_LENGTH &&
|
||||
tag_len != EVP_MD_size(md)) {
|
||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_UNSUPPORTED_TAG_SIZE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (key_len != EVP_AEAD_key_length(ctx->aead)) {
|
||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_KEY_LENGTH);
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t mac_key_len = EVP_MD_size(md);
|
||||
size_t enc_key_len = EVP_CIPHER_key_length(cipher);
|
||||
assert(mac_key_len + enc_key_len + EVP_CIPHER_iv_length(cipher) == key_len);
|
||||
|
||||
AEAD_SSL3_CTX *ssl3_ctx = OPENSSL_malloc(sizeof(AEAD_SSL3_CTX));
|
||||
if (ssl3_ctx == NULL) {
|
||||
OPENSSL_PUT_ERROR(CIPHER, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
EVP_CIPHER_CTX_init(&ssl3_ctx->cipher_ctx);
|
||||
EVP_MD_CTX_init(&ssl3_ctx->md_ctx);
|
||||
|
||||
ctx->aead_state = ssl3_ctx;
|
||||
if (!EVP_CipherInit_ex(&ssl3_ctx->cipher_ctx, cipher, NULL, &key[mac_key_len],
|
||||
&key[mac_key_len + enc_key_len],
|
||||
dir == evp_aead_seal) ||
|
||||
!EVP_DigestInit_ex(&ssl3_ctx->md_ctx, md, NULL) ||
|
||||
!EVP_DigestUpdate(&ssl3_ctx->md_ctx, key, mac_key_len)) {
|
||||
aead_ssl3_cleanup(ctx);
|
||||
ctx->aead_state = NULL;
|
||||
return 0;
|
||||
}
|
||||
EVP_CIPHER_CTX_set_padding(&ssl3_ctx->cipher_ctx, 0);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int aead_ssl3_seal(const EVP_AEAD_CTX *ctx, uint8_t *out,
|
||||
size_t *out_len, size_t max_out_len,
|
||||
const uint8_t *nonce, size_t nonce_len,
|
||||
const uint8_t *in, size_t in_len,
|
||||
const uint8_t *ad, size_t ad_len) {
|
||||
AEAD_SSL3_CTX *ssl3_ctx = (AEAD_SSL3_CTX *)ctx->aead_state;
|
||||
size_t total = 0;
|
||||
|
||||
if (!ssl3_ctx->cipher_ctx.encrypt) {
|
||||
/* Unlike a normal AEAD, an SSL3 AEAD may only be used in one direction. */
|
||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_INVALID_OPERATION);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (in_len + EVP_AEAD_max_overhead(ctx->aead) < in_len ||
|
||||
in_len > INT_MAX) {
|
||||
/* EVP_CIPHER takes int as input. */
|
||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (max_out_len < in_len + EVP_AEAD_max_overhead(ctx->aead)) {
|
||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BUFFER_TOO_SMALL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (nonce_len != 0) {
|
||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_IV_TOO_LARGE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ad_len != 11 - 2 /* length bytes */) {
|
||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_INVALID_AD_SIZE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Compute the MAC. This must be first in case the operation is being done
|
||||
* in-place. */
|
||||
uint8_t mac[EVP_MAX_MD_SIZE];
|
||||
unsigned mac_len;
|
||||
if (!ssl3_mac(ssl3_ctx, mac, &mac_len, ad, ad_len, in, in_len)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Encrypt the input. */
|
||||
int len;
|
||||
if (!EVP_EncryptUpdate(&ssl3_ctx->cipher_ctx, out, &len, in,
|
||||
(int)in_len)) {
|
||||
return 0;
|
||||
}
|
||||
total = len;
|
||||
|
||||
/* Feed the MAC into the cipher. */
|
||||
if (!EVP_EncryptUpdate(&ssl3_ctx->cipher_ctx, out + total, &len, mac,
|
||||
(int)mac_len)) {
|
||||
return 0;
|
||||
}
|
||||
total += len;
|
||||
|
||||
unsigned block_size = EVP_CIPHER_CTX_block_size(&ssl3_ctx->cipher_ctx);
|
||||
if (block_size > 1) {
|
||||
assert(block_size <= 256);
|
||||
assert(EVP_CIPHER_CTX_mode(&ssl3_ctx->cipher_ctx) == EVP_CIPH_CBC_MODE);
|
||||
|
||||
/* Compute padding and feed that into the cipher. */
|
||||
uint8_t padding[256];
|
||||
unsigned padding_len = block_size - ((in_len + mac_len) % block_size);
|
||||
OPENSSL_memset(padding, 0, padding_len - 1);
|
||||
padding[padding_len - 1] = padding_len - 1;
|
||||
if (!EVP_EncryptUpdate(&ssl3_ctx->cipher_ctx, out + total, &len, padding,
|
||||
(int)padding_len)) {
|
||||
return 0;
|
||||
}
|
||||
total += len;
|
||||
}
|
||||
|
||||
if (!EVP_EncryptFinal_ex(&ssl3_ctx->cipher_ctx, out + total, &len)) {
|
||||
return 0;
|
||||
}
|
||||
total += len;
|
||||
|
||||
*out_len = total;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int aead_ssl3_open(const EVP_AEAD_CTX *ctx, uint8_t *out,
|
||||
size_t *out_len, size_t max_out_len,
|
||||
const uint8_t *nonce, size_t nonce_len,
|
||||
const uint8_t *in, size_t in_len,
|
||||
const uint8_t *ad, size_t ad_len) {
|
||||
AEAD_SSL3_CTX *ssl3_ctx = (AEAD_SSL3_CTX *)ctx->aead_state;
|
||||
|
||||
if (ssl3_ctx->cipher_ctx.encrypt) {
|
||||
/* Unlike a normal AEAD, an SSL3 AEAD may only be used in one direction. */
|
||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_INVALID_OPERATION);
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t mac_len = EVP_MD_CTX_size(&ssl3_ctx->md_ctx);
|
||||
if (in_len < mac_len) {
|
||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (max_out_len < in_len) {
|
||||
/* This requires that the caller provide space for the MAC, even though it
|
||||
* will always be removed on return. */
|
||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BUFFER_TOO_SMALL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (nonce_len != 0) {
|
||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ad_len != 11 - 2 /* length bytes */) {
|
||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_INVALID_AD_SIZE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (in_len > INT_MAX) {
|
||||
/* EVP_CIPHER takes int as input. */
|
||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Decrypt to get the plaintext + MAC + padding. */
|
||||
size_t total = 0;
|
||||
int len;
|
||||
if (!EVP_DecryptUpdate(&ssl3_ctx->cipher_ctx, out, &len, in, (int)in_len)) {
|
||||
return 0;
|
||||
}
|
||||
total += len;
|
||||
if (!EVP_DecryptFinal_ex(&ssl3_ctx->cipher_ctx, out + total, &len)) {
|
||||
return 0;
|
||||
}
|
||||
total += len;
|
||||
assert(total == in_len);
|
||||
|
||||
/* Remove CBC padding and MAC. This would normally be timing-sensitive, but
|
||||
* SSLv3 CBC ciphers are already broken. Support will be removed eventually.
|
||||
* https://www.openssl.org/~bodo/ssl-poodle.pdf */
|
||||
size_t data_len;
|
||||
if (EVP_CIPHER_CTX_mode(&ssl3_ctx->cipher_ctx) == EVP_CIPH_CBC_MODE) {
|
||||
unsigned padding_length = out[total - 1];
|
||||
if (total < padding_length + 1 + mac_len) {
|
||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT);
|
||||
return 0;
|
||||
}
|
||||
/* The padding must be minimal. */
|
||||
if (padding_length + 1 > EVP_CIPHER_CTX_block_size(&ssl3_ctx->cipher_ctx)) {
|
||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT);
|
||||
return 0;
|
||||
}
|
||||
data_len = total - padding_length - 1 - mac_len;
|
||||
} else {
|
||||
data_len = total - mac_len;
|
||||
}
|
||||
|
||||
/* Compute the MAC and compare against the one in the record. */
|
||||
uint8_t mac[EVP_MAX_MD_SIZE];
|
||||
if (!ssl3_mac(ssl3_ctx, mac, NULL, ad, ad_len, out, data_len)) {
|
||||
return 0;
|
||||
}
|
||||
if (CRYPTO_memcmp(&out[data_len], mac, mac_len) != 0) {
|
||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT);
|
||||
return 0;
|
||||
}
|
||||
|
||||
*out_len = data_len;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int aead_ssl3_get_iv(const EVP_AEAD_CTX *ctx, const uint8_t **out_iv,
|
||||
size_t *out_iv_len) {
|
||||
AEAD_SSL3_CTX *ssl3_ctx = (AEAD_SSL3_CTX *)ctx->aead_state;
|
||||
const size_t iv_len = EVP_CIPHER_CTX_iv_length(&ssl3_ctx->cipher_ctx);
|
||||
if (iv_len <= 1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
*out_iv = ssl3_ctx->cipher_ctx.iv;
|
||||
*out_iv_len = iv_len;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int aead_aes_128_cbc_sha1_ssl3_init(EVP_AEAD_CTX *ctx, const uint8_t *key,
|
||||
size_t key_len, size_t tag_len,
|
||||
enum evp_aead_direction_t dir) {
|
||||
return aead_ssl3_init(ctx, key, key_len, tag_len, dir, EVP_aes_128_cbc(),
|
||||
EVP_sha1());
|
||||
}
|
||||
|
||||
static int aead_aes_256_cbc_sha1_ssl3_init(EVP_AEAD_CTX *ctx, const uint8_t *key,
|
||||
size_t key_len, size_t tag_len,
|
||||
enum evp_aead_direction_t dir) {
|
||||
return aead_ssl3_init(ctx, key, key_len, tag_len, dir, EVP_aes_256_cbc(),
|
||||
EVP_sha1());
|
||||
}
|
||||
static int aead_des_ede3_cbc_sha1_ssl3_init(EVP_AEAD_CTX *ctx,
|
||||
const uint8_t *key, size_t key_len,
|
||||
size_t tag_len,
|
||||
enum evp_aead_direction_t dir) {
|
||||
return aead_ssl3_init(ctx, key, key_len, tag_len, dir, EVP_des_ede3_cbc(),
|
||||
EVP_sha1());
|
||||
}
|
||||
|
||||
static int aead_null_sha1_ssl3_init(EVP_AEAD_CTX *ctx, const uint8_t *key,
|
||||
size_t key_len, size_t tag_len,
|
||||
enum evp_aead_direction_t dir) {
|
||||
return aead_ssl3_init(ctx, key, key_len, tag_len, dir, EVP_enc_null(),
|
||||
EVP_sha1());
|
||||
}
|
||||
|
||||
static const EVP_AEAD aead_aes_128_cbc_sha1_ssl3 = {
|
||||
SHA_DIGEST_LENGTH + 16 + 16, /* key len (SHA1 + AES128 + IV) */
|
||||
0, /* nonce len */
|
||||
16 + SHA_DIGEST_LENGTH, /* overhead (padding + SHA1) */
|
||||
SHA_DIGEST_LENGTH, /* max tag length */
|
||||
NULL, /* init */
|
||||
aead_aes_128_cbc_sha1_ssl3_init,
|
||||
aead_ssl3_cleanup,
|
||||
aead_ssl3_seal,
|
||||
aead_ssl3_open,
|
||||
aead_ssl3_get_iv,
|
||||
};
|
||||
|
||||
static const EVP_AEAD aead_aes_256_cbc_sha1_ssl3 = {
|
||||
SHA_DIGEST_LENGTH + 32 + 16, /* key len (SHA1 + AES256 + IV) */
|
||||
0, /* nonce len */
|
||||
16 + SHA_DIGEST_LENGTH, /* overhead (padding + SHA1) */
|
||||
SHA_DIGEST_LENGTH, /* max tag length */
|
||||
NULL, /* init */
|
||||
aead_aes_256_cbc_sha1_ssl3_init,
|
||||
aead_ssl3_cleanup,
|
||||
aead_ssl3_seal,
|
||||
aead_ssl3_open,
|
||||
aead_ssl3_get_iv,
|
||||
};
|
||||
|
||||
static const EVP_AEAD aead_des_ede3_cbc_sha1_ssl3 = {
|
||||
SHA_DIGEST_LENGTH + 24 + 8, /* key len (SHA1 + 3DES + IV) */
|
||||
0, /* nonce len */
|
||||
8 + SHA_DIGEST_LENGTH, /* overhead (padding + SHA1) */
|
||||
SHA_DIGEST_LENGTH, /* max tag length */
|
||||
NULL, /* init */
|
||||
aead_des_ede3_cbc_sha1_ssl3_init,
|
||||
aead_ssl3_cleanup,
|
||||
aead_ssl3_seal,
|
||||
aead_ssl3_open,
|
||||
aead_ssl3_get_iv,
|
||||
};
|
||||
|
||||
static const EVP_AEAD aead_null_sha1_ssl3 = {
|
||||
SHA_DIGEST_LENGTH, /* key len */
|
||||
0, /* nonce len */
|
||||
SHA_DIGEST_LENGTH, /* overhead (SHA1) */
|
||||
SHA_DIGEST_LENGTH, /* max tag length */
|
||||
NULL, /* init */
|
||||
aead_null_sha1_ssl3_init,
|
||||
aead_ssl3_cleanup,
|
||||
aead_ssl3_seal,
|
||||
aead_ssl3_open,
|
||||
NULL, /* get_iv */
|
||||
};
|
||||
|
||||
const EVP_AEAD *EVP_aead_aes_128_cbc_sha1_ssl3(void) {
|
||||
return &aead_aes_128_cbc_sha1_ssl3;
|
||||
}
|
||||
|
||||
const EVP_AEAD *EVP_aead_aes_256_cbc_sha1_ssl3(void) {
|
||||
return &aead_aes_256_cbc_sha1_ssl3;
|
||||
}
|
||||
|
||||
const EVP_AEAD *EVP_aead_des_ede3_cbc_sha1_ssl3(void) {
|
||||
return &aead_des_ede3_cbc_sha1_ssl3;
|
||||
}
|
||||
|
||||
const EVP_AEAD *EVP_aead_null_sha1_ssl3(void) { return &aead_null_sha1_ssl3; }
|
||||
@@ -1,602 +0,0 @@
|
||||
/* Copyright (c) 2014, Google Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
|
||||
|
||||
#include <assert.h>
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl/aead.h>
|
||||
#include <openssl/cipher.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/hmac.h>
|
||||
#include <openssl/md5.h>
|
||||
#include <openssl/mem.h>
|
||||
#include <openssl/sha.h>
|
||||
#include <openssl/type_check.h>
|
||||
|
||||
#include "../internal.h"
|
||||
#include "internal.h"
|
||||
|
||||
|
||||
typedef struct {
|
||||
EVP_CIPHER_CTX cipher_ctx;
|
||||
HMAC_CTX hmac_ctx;
|
||||
/* mac_key is the portion of the key used for the MAC. It is retained
|
||||
* separately for the constant-time CBC code. */
|
||||
uint8_t mac_key[EVP_MAX_MD_SIZE];
|
||||
uint8_t mac_key_len;
|
||||
/* implicit_iv is one iff this is a pre-TLS-1.1 CBC cipher without an explicit
|
||||
* IV. */
|
||||
char implicit_iv;
|
||||
} AEAD_TLS_CTX;
|
||||
|
||||
OPENSSL_COMPILE_ASSERT(EVP_MAX_MD_SIZE < 256, mac_key_len_fits_in_uint8_t);
|
||||
|
||||
static void aead_tls_cleanup(EVP_AEAD_CTX *ctx) {
|
||||
AEAD_TLS_CTX *tls_ctx = (AEAD_TLS_CTX *)ctx->aead_state;
|
||||
EVP_CIPHER_CTX_cleanup(&tls_ctx->cipher_ctx);
|
||||
HMAC_CTX_cleanup(&tls_ctx->hmac_ctx);
|
||||
OPENSSL_cleanse(&tls_ctx->mac_key, sizeof(tls_ctx->mac_key));
|
||||
OPENSSL_free(tls_ctx);
|
||||
ctx->aead_state = NULL;
|
||||
}
|
||||
|
||||
static int aead_tls_init(EVP_AEAD_CTX *ctx, const uint8_t *key, size_t key_len,
|
||||
size_t tag_len, enum evp_aead_direction_t dir,
|
||||
const EVP_CIPHER *cipher, const EVP_MD *md,
|
||||
char implicit_iv) {
|
||||
if (tag_len != EVP_AEAD_DEFAULT_TAG_LENGTH &&
|
||||
tag_len != EVP_MD_size(md)) {
|
||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_UNSUPPORTED_TAG_SIZE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (key_len != EVP_AEAD_key_length(ctx->aead)) {
|
||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_KEY_LENGTH);
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t mac_key_len = EVP_MD_size(md);
|
||||
size_t enc_key_len = EVP_CIPHER_key_length(cipher);
|
||||
assert(mac_key_len + enc_key_len +
|
||||
(implicit_iv ? EVP_CIPHER_iv_length(cipher) : 0) == key_len);
|
||||
|
||||
AEAD_TLS_CTX *tls_ctx = OPENSSL_malloc(sizeof(AEAD_TLS_CTX));
|
||||
if (tls_ctx == NULL) {
|
||||
OPENSSL_PUT_ERROR(CIPHER, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
EVP_CIPHER_CTX_init(&tls_ctx->cipher_ctx);
|
||||
HMAC_CTX_init(&tls_ctx->hmac_ctx);
|
||||
assert(mac_key_len <= EVP_MAX_MD_SIZE);
|
||||
OPENSSL_memcpy(tls_ctx->mac_key, key, mac_key_len);
|
||||
tls_ctx->mac_key_len = (uint8_t)mac_key_len;
|
||||
tls_ctx->implicit_iv = implicit_iv;
|
||||
|
||||
ctx->aead_state = tls_ctx;
|
||||
if (!EVP_CipherInit_ex(&tls_ctx->cipher_ctx, cipher, NULL, &key[mac_key_len],
|
||||
implicit_iv ? &key[mac_key_len + enc_key_len] : NULL,
|
||||
dir == evp_aead_seal) ||
|
||||
!HMAC_Init_ex(&tls_ctx->hmac_ctx, key, mac_key_len, md, NULL)) {
|
||||
aead_tls_cleanup(ctx);
|
||||
ctx->aead_state = NULL;
|
||||
return 0;
|
||||
}
|
||||
EVP_CIPHER_CTX_set_padding(&tls_ctx->cipher_ctx, 0);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int aead_tls_seal(const EVP_AEAD_CTX *ctx, uint8_t *out,
|
||||
size_t *out_len, size_t max_out_len,
|
||||
const uint8_t *nonce, size_t nonce_len,
|
||||
const uint8_t *in, size_t in_len,
|
||||
const uint8_t *ad, size_t ad_len) {
|
||||
AEAD_TLS_CTX *tls_ctx = (AEAD_TLS_CTX *)ctx->aead_state;
|
||||
size_t total = 0;
|
||||
|
||||
if (!tls_ctx->cipher_ctx.encrypt) {
|
||||
/* Unlike a normal AEAD, a TLS AEAD may only be used in one direction. */
|
||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_INVALID_OPERATION);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (in_len + EVP_AEAD_max_overhead(ctx->aead) < in_len ||
|
||||
in_len > INT_MAX) {
|
||||
/* EVP_CIPHER takes int as input. */
|
||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (max_out_len < in_len + EVP_AEAD_max_overhead(ctx->aead)) {
|
||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BUFFER_TOO_SMALL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (nonce_len != EVP_AEAD_nonce_length(ctx->aead)) {
|
||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_INVALID_NONCE_SIZE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ad_len != 13 - 2 /* length bytes */) {
|
||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_INVALID_AD_SIZE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* To allow for CBC mode which changes cipher length, |ad| doesn't include the
|
||||
* length for legacy ciphers. */
|
||||
uint8_t ad_extra[2];
|
||||
ad_extra[0] = (uint8_t)(in_len >> 8);
|
||||
ad_extra[1] = (uint8_t)(in_len & 0xff);
|
||||
|
||||
/* Compute the MAC. This must be first in case the operation is being done
|
||||
* in-place. */
|
||||
uint8_t mac[EVP_MAX_MD_SIZE];
|
||||
unsigned mac_len;
|
||||
if (!HMAC_Init_ex(&tls_ctx->hmac_ctx, NULL, 0, NULL, NULL) ||
|
||||
!HMAC_Update(&tls_ctx->hmac_ctx, ad, ad_len) ||
|
||||
!HMAC_Update(&tls_ctx->hmac_ctx, ad_extra, sizeof(ad_extra)) ||
|
||||
!HMAC_Update(&tls_ctx->hmac_ctx, in, in_len) ||
|
||||
!HMAC_Final(&tls_ctx->hmac_ctx, mac, &mac_len)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Configure the explicit IV. */
|
||||
if (EVP_CIPHER_CTX_mode(&tls_ctx->cipher_ctx) == EVP_CIPH_CBC_MODE &&
|
||||
!tls_ctx->implicit_iv &&
|
||||
!EVP_EncryptInit_ex(&tls_ctx->cipher_ctx, NULL, NULL, NULL, nonce)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Encrypt the input. */
|
||||
int len;
|
||||
if (!EVP_EncryptUpdate(&tls_ctx->cipher_ctx, out, &len, in,
|
||||
(int)in_len)) {
|
||||
return 0;
|
||||
}
|
||||
total = len;
|
||||
|
||||
/* Feed the MAC into the cipher. */
|
||||
if (!EVP_EncryptUpdate(&tls_ctx->cipher_ctx, out + total, &len, mac,
|
||||
(int)mac_len)) {
|
||||
return 0;
|
||||
}
|
||||
total += len;
|
||||
|
||||
unsigned block_size = EVP_CIPHER_CTX_block_size(&tls_ctx->cipher_ctx);
|
||||
if (block_size > 1) {
|
||||
assert(block_size <= 256);
|
||||
assert(EVP_CIPHER_CTX_mode(&tls_ctx->cipher_ctx) == EVP_CIPH_CBC_MODE);
|
||||
|
||||
/* Compute padding and feed that into the cipher. */
|
||||
uint8_t padding[256];
|
||||
unsigned padding_len = block_size - ((in_len + mac_len) % block_size);
|
||||
OPENSSL_memset(padding, padding_len - 1, padding_len);
|
||||
if (!EVP_EncryptUpdate(&tls_ctx->cipher_ctx, out + total, &len, padding,
|
||||
(int)padding_len)) {
|
||||
return 0;
|
||||
}
|
||||
total += len;
|
||||
}
|
||||
|
||||
if (!EVP_EncryptFinal_ex(&tls_ctx->cipher_ctx, out + total, &len)) {
|
||||
return 0;
|
||||
}
|
||||
total += len;
|
||||
|
||||
*out_len = total;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int aead_tls_open(const EVP_AEAD_CTX *ctx, uint8_t *out,
|
||||
size_t *out_len, size_t max_out_len,
|
||||
const uint8_t *nonce, size_t nonce_len,
|
||||
const uint8_t *in, size_t in_len,
|
||||
const uint8_t *ad, size_t ad_len) {
|
||||
AEAD_TLS_CTX *tls_ctx = (AEAD_TLS_CTX *)ctx->aead_state;
|
||||
|
||||
if (tls_ctx->cipher_ctx.encrypt) {
|
||||
/* Unlike a normal AEAD, a TLS AEAD may only be used in one direction. */
|
||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_INVALID_OPERATION);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (in_len < HMAC_size(&tls_ctx->hmac_ctx)) {
|
||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (max_out_len < in_len) {
|
||||
/* This requires that the caller provide space for the MAC, even though it
|
||||
* will always be removed on return. */
|
||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BUFFER_TOO_SMALL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (nonce_len != EVP_AEAD_nonce_length(ctx->aead)) {
|
||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_INVALID_NONCE_SIZE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ad_len != 13 - 2 /* length bytes */) {
|
||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_INVALID_AD_SIZE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (in_len > INT_MAX) {
|
||||
/* EVP_CIPHER takes int as input. */
|
||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Configure the explicit IV. */
|
||||
if (EVP_CIPHER_CTX_mode(&tls_ctx->cipher_ctx) == EVP_CIPH_CBC_MODE &&
|
||||
!tls_ctx->implicit_iv &&
|
||||
!EVP_DecryptInit_ex(&tls_ctx->cipher_ctx, NULL, NULL, NULL, nonce)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Decrypt to get the plaintext + MAC + padding. */
|
||||
size_t total = 0;
|
||||
int len;
|
||||
if (!EVP_DecryptUpdate(&tls_ctx->cipher_ctx, out, &len, in, (int)in_len)) {
|
||||
return 0;
|
||||
}
|
||||
total += len;
|
||||
if (!EVP_DecryptFinal_ex(&tls_ctx->cipher_ctx, out + total, &len)) {
|
||||
return 0;
|
||||
}
|
||||
total += len;
|
||||
assert(total == in_len);
|
||||
|
||||
/* Remove CBC padding. Code from here on is timing-sensitive with respect to
|
||||
* |padding_ok| and |data_plus_mac_len| for CBC ciphers. */
|
||||
unsigned padding_ok, data_plus_mac_len;
|
||||
if (EVP_CIPHER_CTX_mode(&tls_ctx->cipher_ctx) == EVP_CIPH_CBC_MODE) {
|
||||
if (!EVP_tls_cbc_remove_padding(
|
||||
&padding_ok, &data_plus_mac_len, out, total,
|
||||
EVP_CIPHER_CTX_block_size(&tls_ctx->cipher_ctx),
|
||||
(unsigned)HMAC_size(&tls_ctx->hmac_ctx))) {
|
||||
/* Publicly invalid. This can be rejected in non-constant time. */
|
||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT);
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
padding_ok = ~0u;
|
||||
data_plus_mac_len = total;
|
||||
/* |data_plus_mac_len| = |total| = |in_len| at this point. |in_len| has
|
||||
* already been checked against the MAC size at the top of the function. */
|
||||
assert(data_plus_mac_len >= HMAC_size(&tls_ctx->hmac_ctx));
|
||||
}
|
||||
unsigned data_len = data_plus_mac_len - HMAC_size(&tls_ctx->hmac_ctx);
|
||||
|
||||
/* At this point, if the padding is valid, the first |data_plus_mac_len| bytes
|
||||
* after |out| are the plaintext and MAC. Otherwise, |data_plus_mac_len| is
|
||||
* still large enough to extract a MAC, but it will be irrelevant. */
|
||||
|
||||
/* To allow for CBC mode which changes cipher length, |ad| doesn't include the
|
||||
* length for legacy ciphers. */
|
||||
uint8_t ad_fixed[13];
|
||||
OPENSSL_memcpy(ad_fixed, ad, 11);
|
||||
ad_fixed[11] = (uint8_t)(data_len >> 8);
|
||||
ad_fixed[12] = (uint8_t)(data_len & 0xff);
|
||||
ad_len += 2;
|
||||
|
||||
/* Compute the MAC and extract the one in the record. */
|
||||
uint8_t mac[EVP_MAX_MD_SIZE];
|
||||
size_t mac_len;
|
||||
uint8_t record_mac_tmp[EVP_MAX_MD_SIZE];
|
||||
uint8_t *record_mac;
|
||||
if (EVP_CIPHER_CTX_mode(&tls_ctx->cipher_ctx) == EVP_CIPH_CBC_MODE &&
|
||||
EVP_tls_cbc_record_digest_supported(tls_ctx->hmac_ctx.md)) {
|
||||
if (!EVP_tls_cbc_digest_record(tls_ctx->hmac_ctx.md, mac, &mac_len,
|
||||
ad_fixed, out, data_plus_mac_len, total,
|
||||
tls_ctx->mac_key, tls_ctx->mac_key_len)) {
|
||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT);
|
||||
return 0;
|
||||
}
|
||||
assert(mac_len == HMAC_size(&tls_ctx->hmac_ctx));
|
||||
|
||||
record_mac = record_mac_tmp;
|
||||
EVP_tls_cbc_copy_mac(record_mac, mac_len, out, data_plus_mac_len, total);
|
||||
} else {
|
||||
/* We should support the constant-time path for all CBC-mode ciphers
|
||||
* implemented. */
|
||||
assert(EVP_CIPHER_CTX_mode(&tls_ctx->cipher_ctx) != EVP_CIPH_CBC_MODE);
|
||||
|
||||
unsigned mac_len_u;
|
||||
if (!HMAC_Init_ex(&tls_ctx->hmac_ctx, NULL, 0, NULL, NULL) ||
|
||||
!HMAC_Update(&tls_ctx->hmac_ctx, ad_fixed, ad_len) ||
|
||||
!HMAC_Update(&tls_ctx->hmac_ctx, out, data_len) ||
|
||||
!HMAC_Final(&tls_ctx->hmac_ctx, mac, &mac_len_u)) {
|
||||
return 0;
|
||||
}
|
||||
mac_len = mac_len_u;
|
||||
|
||||
assert(mac_len == HMAC_size(&tls_ctx->hmac_ctx));
|
||||
record_mac = &out[data_len];
|
||||
}
|
||||
|
||||
/* Perform the MAC check and the padding check in constant-time. It should be
|
||||
* safe to simply perform the padding check first, but it would not be under a
|
||||
* different choice of MAC location on padding failure. See
|
||||
* EVP_tls_cbc_remove_padding. */
|
||||
unsigned good = constant_time_eq_int(CRYPTO_memcmp(record_mac, mac, mac_len),
|
||||
0);
|
||||
good &= padding_ok;
|
||||
if (!good) {
|
||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* End of timing-sensitive code. */
|
||||
|
||||
*out_len = data_len;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int aead_aes_128_cbc_sha1_tls_init(EVP_AEAD_CTX *ctx, const uint8_t *key,
|
||||
size_t key_len, size_t tag_len,
|
||||
enum evp_aead_direction_t dir) {
|
||||
return aead_tls_init(ctx, key, key_len, tag_len, dir, EVP_aes_128_cbc(),
|
||||
EVP_sha1(), 0);
|
||||
}
|
||||
|
||||
static int aead_aes_128_cbc_sha1_tls_implicit_iv_init(
|
||||
EVP_AEAD_CTX *ctx, const uint8_t *key, size_t key_len, size_t tag_len,
|
||||
enum evp_aead_direction_t dir) {
|
||||
return aead_tls_init(ctx, key, key_len, tag_len, dir, EVP_aes_128_cbc(),
|
||||
EVP_sha1(), 1);
|
||||
}
|
||||
|
||||
static int aead_aes_128_cbc_sha256_tls_init(EVP_AEAD_CTX *ctx,
|
||||
const uint8_t *key, size_t key_len,
|
||||
size_t tag_len,
|
||||
enum evp_aead_direction_t dir) {
|
||||
return aead_tls_init(ctx, key, key_len, tag_len, dir, EVP_aes_128_cbc(),
|
||||
EVP_sha256(), 0);
|
||||
}
|
||||
|
||||
static int aead_aes_256_cbc_sha1_tls_init(EVP_AEAD_CTX *ctx, const uint8_t *key,
|
||||
size_t key_len, size_t tag_len,
|
||||
enum evp_aead_direction_t dir) {
|
||||
return aead_tls_init(ctx, key, key_len, tag_len, dir, EVP_aes_256_cbc(),
|
||||
EVP_sha1(), 0);
|
||||
}
|
||||
|
||||
static int aead_aes_256_cbc_sha1_tls_implicit_iv_init(
|
||||
EVP_AEAD_CTX *ctx, const uint8_t *key, size_t key_len, size_t tag_len,
|
||||
enum evp_aead_direction_t dir) {
|
||||
return aead_tls_init(ctx, key, key_len, tag_len, dir, EVP_aes_256_cbc(),
|
||||
EVP_sha1(), 1);
|
||||
}
|
||||
|
||||
static int aead_aes_256_cbc_sha256_tls_init(EVP_AEAD_CTX *ctx,
|
||||
const uint8_t *key, size_t key_len,
|
||||
size_t tag_len,
|
||||
enum evp_aead_direction_t dir) {
|
||||
return aead_tls_init(ctx, key, key_len, tag_len, dir, EVP_aes_256_cbc(),
|
||||
EVP_sha256(), 0);
|
||||
}
|
||||
|
||||
static int aead_aes_256_cbc_sha384_tls_init(EVP_AEAD_CTX *ctx,
|
||||
const uint8_t *key, size_t key_len,
|
||||
size_t tag_len,
|
||||
enum evp_aead_direction_t dir) {
|
||||
return aead_tls_init(ctx, key, key_len, tag_len, dir, EVP_aes_256_cbc(),
|
||||
EVP_sha384(), 0);
|
||||
}
|
||||
|
||||
static int aead_des_ede3_cbc_sha1_tls_init(EVP_AEAD_CTX *ctx,
|
||||
const uint8_t *key, size_t key_len,
|
||||
size_t tag_len,
|
||||
enum evp_aead_direction_t dir) {
|
||||
return aead_tls_init(ctx, key, key_len, tag_len, dir, EVP_des_ede3_cbc(),
|
||||
EVP_sha1(), 0);
|
||||
}
|
||||
|
||||
static int aead_des_ede3_cbc_sha1_tls_implicit_iv_init(
|
||||
EVP_AEAD_CTX *ctx, const uint8_t *key, size_t key_len, size_t tag_len,
|
||||
enum evp_aead_direction_t dir) {
|
||||
return aead_tls_init(ctx, key, key_len, tag_len, dir, EVP_des_ede3_cbc(),
|
||||
EVP_sha1(), 1);
|
||||
}
|
||||
|
||||
static int aead_tls_get_iv(const EVP_AEAD_CTX *ctx, const uint8_t **out_iv,
|
||||
size_t *out_iv_len) {
|
||||
const AEAD_TLS_CTX *tls_ctx = (AEAD_TLS_CTX*) ctx->aead_state;
|
||||
const size_t iv_len = EVP_CIPHER_CTX_iv_length(&tls_ctx->cipher_ctx);
|
||||
if (iv_len <= 1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
*out_iv = tls_ctx->cipher_ctx.iv;
|
||||
*out_iv_len = iv_len;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int aead_null_sha1_tls_init(EVP_AEAD_CTX *ctx, const uint8_t *key,
|
||||
size_t key_len, size_t tag_len,
|
||||
enum evp_aead_direction_t dir) {
|
||||
return aead_tls_init(ctx, key, key_len, tag_len, dir, EVP_enc_null(),
|
||||
EVP_sha1(), 1 /* implicit iv */);
|
||||
}
|
||||
|
||||
static const EVP_AEAD aead_aes_128_cbc_sha1_tls = {
|
||||
SHA_DIGEST_LENGTH + 16, /* key len (SHA1 + AES128) */
|
||||
16, /* nonce len (IV) */
|
||||
16 + SHA_DIGEST_LENGTH, /* overhead (padding + SHA1) */
|
||||
SHA_DIGEST_LENGTH, /* max tag length */
|
||||
NULL, /* init */
|
||||
aead_aes_128_cbc_sha1_tls_init,
|
||||
aead_tls_cleanup,
|
||||
aead_tls_seal,
|
||||
aead_tls_open,
|
||||
NULL, /* get_iv */
|
||||
};
|
||||
|
||||
static const EVP_AEAD aead_aes_128_cbc_sha1_tls_implicit_iv = {
|
||||
SHA_DIGEST_LENGTH + 16 + 16, /* key len (SHA1 + AES128 + IV) */
|
||||
0, /* nonce len */
|
||||
16 + SHA_DIGEST_LENGTH, /* overhead (padding + SHA1) */
|
||||
SHA_DIGEST_LENGTH, /* max tag length */
|
||||
NULL, /* init */
|
||||
aead_aes_128_cbc_sha1_tls_implicit_iv_init,
|
||||
aead_tls_cleanup,
|
||||
aead_tls_seal,
|
||||
aead_tls_open,
|
||||
aead_tls_get_iv, /* get_iv */
|
||||
};
|
||||
|
||||
static const EVP_AEAD aead_aes_128_cbc_sha256_tls = {
|
||||
SHA256_DIGEST_LENGTH + 16, /* key len (SHA256 + AES128) */
|
||||
16, /* nonce len (IV) */
|
||||
16 + SHA256_DIGEST_LENGTH, /* overhead (padding + SHA256) */
|
||||
SHA256_DIGEST_LENGTH, /* max tag length */
|
||||
NULL, /* init */
|
||||
aead_aes_128_cbc_sha256_tls_init,
|
||||
aead_tls_cleanup,
|
||||
aead_tls_seal,
|
||||
aead_tls_open,
|
||||
NULL, /* get_iv */
|
||||
};
|
||||
|
||||
static const EVP_AEAD aead_aes_256_cbc_sha1_tls = {
|
||||
SHA_DIGEST_LENGTH + 32, /* key len (SHA1 + AES256) */
|
||||
16, /* nonce len (IV) */
|
||||
16 + SHA_DIGEST_LENGTH, /* overhead (padding + SHA1) */
|
||||
SHA_DIGEST_LENGTH, /* max tag length */
|
||||
NULL, /* init */
|
||||
aead_aes_256_cbc_sha1_tls_init,
|
||||
aead_tls_cleanup,
|
||||
aead_tls_seal,
|
||||
aead_tls_open,
|
||||
NULL, /* get_iv */
|
||||
};
|
||||
|
||||
static const EVP_AEAD aead_aes_256_cbc_sha1_tls_implicit_iv = {
|
||||
SHA_DIGEST_LENGTH + 32 + 16, /* key len (SHA1 + AES256 + IV) */
|
||||
0, /* nonce len */
|
||||
16 + SHA_DIGEST_LENGTH, /* overhead (padding + SHA1) */
|
||||
SHA_DIGEST_LENGTH, /* max tag length */
|
||||
NULL, /* init */
|
||||
aead_aes_256_cbc_sha1_tls_implicit_iv_init,
|
||||
aead_tls_cleanup,
|
||||
aead_tls_seal,
|
||||
aead_tls_open,
|
||||
aead_tls_get_iv, /* get_iv */
|
||||
};
|
||||
|
||||
static const EVP_AEAD aead_aes_256_cbc_sha256_tls = {
|
||||
SHA256_DIGEST_LENGTH + 32, /* key len (SHA256 + AES256) */
|
||||
16, /* nonce len (IV) */
|
||||
16 + SHA256_DIGEST_LENGTH, /* overhead (padding + SHA256) */
|
||||
SHA256_DIGEST_LENGTH, /* max tag length */
|
||||
NULL, /* init */
|
||||
aead_aes_256_cbc_sha256_tls_init,
|
||||
aead_tls_cleanup,
|
||||
aead_tls_seal,
|
||||
aead_tls_open,
|
||||
NULL, /* get_iv */
|
||||
};
|
||||
|
||||
static const EVP_AEAD aead_aes_256_cbc_sha384_tls = {
|
||||
SHA384_DIGEST_LENGTH + 32, /* key len (SHA384 + AES256) */
|
||||
16, /* nonce len (IV) */
|
||||
16 + SHA384_DIGEST_LENGTH, /* overhead (padding + SHA384) */
|
||||
SHA384_DIGEST_LENGTH, /* max tag length */
|
||||
NULL, /* init */
|
||||
aead_aes_256_cbc_sha384_tls_init,
|
||||
aead_tls_cleanup,
|
||||
aead_tls_seal,
|
||||
aead_tls_open,
|
||||
NULL, /* get_iv */
|
||||
};
|
||||
|
||||
static const EVP_AEAD aead_des_ede3_cbc_sha1_tls = {
|
||||
SHA_DIGEST_LENGTH + 24, /* key len (SHA1 + 3DES) */
|
||||
8, /* nonce len (IV) */
|
||||
8 + SHA_DIGEST_LENGTH, /* overhead (padding + SHA1) */
|
||||
SHA_DIGEST_LENGTH, /* max tag length */
|
||||
NULL, /* init */
|
||||
aead_des_ede3_cbc_sha1_tls_init,
|
||||
aead_tls_cleanup,
|
||||
aead_tls_seal,
|
||||
aead_tls_open,
|
||||
NULL, /* get_iv */
|
||||
};
|
||||
|
||||
static const EVP_AEAD aead_des_ede3_cbc_sha1_tls_implicit_iv = {
|
||||
SHA_DIGEST_LENGTH + 24 + 8, /* key len (SHA1 + 3DES + IV) */
|
||||
0, /* nonce len */
|
||||
8 + SHA_DIGEST_LENGTH, /* overhead (padding + SHA1) */
|
||||
SHA_DIGEST_LENGTH, /* max tag length */
|
||||
NULL, /* init */
|
||||
aead_des_ede3_cbc_sha1_tls_implicit_iv_init,
|
||||
aead_tls_cleanup,
|
||||
aead_tls_seal,
|
||||
aead_tls_open,
|
||||
aead_tls_get_iv, /* get_iv */
|
||||
};
|
||||
|
||||
static const EVP_AEAD aead_null_sha1_tls = {
|
||||
SHA_DIGEST_LENGTH, /* key len */
|
||||
0, /* nonce len */
|
||||
SHA_DIGEST_LENGTH, /* overhead (SHA1) */
|
||||
SHA_DIGEST_LENGTH, /* max tag length */
|
||||
NULL, /* init */
|
||||
aead_null_sha1_tls_init,
|
||||
aead_tls_cleanup,
|
||||
aead_tls_seal,
|
||||
aead_tls_open,
|
||||
NULL, /* get_iv */
|
||||
};
|
||||
|
||||
const EVP_AEAD *EVP_aead_aes_128_cbc_sha1_tls(void) {
|
||||
return &aead_aes_128_cbc_sha1_tls;
|
||||
}
|
||||
|
||||
const EVP_AEAD *EVP_aead_aes_128_cbc_sha1_tls_implicit_iv(void) {
|
||||
return &aead_aes_128_cbc_sha1_tls_implicit_iv;
|
||||
}
|
||||
|
||||
const EVP_AEAD *EVP_aead_aes_128_cbc_sha256_tls(void) {
|
||||
return &aead_aes_128_cbc_sha256_tls;
|
||||
}
|
||||
|
||||
const EVP_AEAD *EVP_aead_aes_256_cbc_sha1_tls(void) {
|
||||
return &aead_aes_256_cbc_sha1_tls;
|
||||
}
|
||||
|
||||
const EVP_AEAD *EVP_aead_aes_256_cbc_sha1_tls_implicit_iv(void) {
|
||||
return &aead_aes_256_cbc_sha1_tls_implicit_iv;
|
||||
}
|
||||
|
||||
const EVP_AEAD *EVP_aead_aes_256_cbc_sha256_tls(void) {
|
||||
return &aead_aes_256_cbc_sha256_tls;
|
||||
}
|
||||
|
||||
const EVP_AEAD *EVP_aead_aes_256_cbc_sha384_tls(void) {
|
||||
return &aead_aes_256_cbc_sha384_tls;
|
||||
}
|
||||
|
||||
const EVP_AEAD *EVP_aead_des_ede3_cbc_sha1_tls(void) {
|
||||
return &aead_des_ede3_cbc_sha1_tls;
|
||||
}
|
||||
|
||||
const EVP_AEAD *EVP_aead_des_ede3_cbc_sha1_tls_implicit_iv(void) {
|
||||
return &aead_des_ede3_cbc_sha1_tls_implicit_iv;
|
||||
}
|
||||
|
||||
const EVP_AEAD *EVP_aead_null_sha1_tls(void) { return &aead_null_sha1_tls; }
|
||||
@@ -1,162 +0,0 @@
|
||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young (eay@cryptsoft.com).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young (eay@cryptsoft.com)"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.] */
|
||||
|
||||
#ifndef OPENSSL_HEADER_CIPHER_INTERNAL_H
|
||||
#define OPENSSL_HEADER_CIPHER_INTERNAL_H
|
||||
|
||||
#include <openssl/base.h>
|
||||
|
||||
#include <openssl/aead.h>
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/* EVP_CIPH_MODE_MASK contains the bits of |flags| that represent the mode. */
|
||||
#define EVP_CIPH_MODE_MASK 0x3f
|
||||
|
||||
|
||||
/* EVP_AEAD represents a specific AEAD algorithm. */
|
||||
struct evp_aead_st {
|
||||
uint8_t key_len;
|
||||
uint8_t nonce_len;
|
||||
uint8_t overhead;
|
||||
uint8_t max_tag_len;
|
||||
|
||||
/* init initialises an |EVP_AEAD_CTX|. If this call returns zero then
|
||||
* |cleanup| will not be called for that context. */
|
||||
int (*init)(EVP_AEAD_CTX *, const uint8_t *key, size_t key_len,
|
||||
size_t tag_len);
|
||||
int (*init_with_direction)(EVP_AEAD_CTX *, const uint8_t *key, size_t key_len,
|
||||
size_t tag_len, enum evp_aead_direction_t dir);
|
||||
void (*cleanup)(EVP_AEAD_CTX *);
|
||||
|
||||
int (*seal)(const EVP_AEAD_CTX *ctx, uint8_t *out, size_t *out_len,
|
||||
size_t max_out_len, const uint8_t *nonce, size_t nonce_len,
|
||||
const uint8_t *in, size_t in_len, const uint8_t *ad,
|
||||
size_t ad_len);
|
||||
|
||||
int (*open)(const EVP_AEAD_CTX *ctx, uint8_t *out, size_t *out_len,
|
||||
size_t max_out_len, const uint8_t *nonce, size_t nonce_len,
|
||||
const uint8_t *in, size_t in_len, const uint8_t *ad,
|
||||
size_t ad_len);
|
||||
|
||||
int (*get_iv)(const EVP_AEAD_CTX *ctx, const uint8_t **out_iv,
|
||||
size_t *out_len);
|
||||
};
|
||||
|
||||
|
||||
/* EVP_tls_cbc_get_padding determines the padding from the decrypted, TLS, CBC
|
||||
* record in |in|. This decrypted record should not include any "decrypted"
|
||||
* explicit IV. If the record is publicly invalid, it returns zero. Otherwise,
|
||||
* it returns one and sets |*out_padding_ok| to all ones (0xfff..f) if the
|
||||
* padding is valid and zero otherwise. It then sets |*out_len| to the length
|
||||
* with the padding removed or |in_len| if invalid.
|
||||
*
|
||||
* If the function returns one, it runs in time independent of the contents of
|
||||
* |in|. It is also guaranteed that |*out_len| >= |mac_size|, satisfying
|
||||
* |EVP_tls_cbc_copy_mac|'s precondition. */
|
||||
int EVP_tls_cbc_remove_padding(unsigned *out_padding_ok, unsigned *out_len,
|
||||
const uint8_t *in, unsigned in_len,
|
||||
unsigned block_size, unsigned mac_size);
|
||||
|
||||
/* EVP_tls_cbc_copy_mac copies |md_size| bytes from the end of the first
|
||||
* |in_len| bytes of |in| to |out| in constant time (independent of the concrete
|
||||
* value of |in_len|, which may vary within a 256-byte window). |in| must point
|
||||
* to a buffer of |orig_len| bytes.
|
||||
*
|
||||
* On entry:
|
||||
* orig_len >= in_len >= md_size
|
||||
* md_size <= EVP_MAX_MD_SIZE */
|
||||
void EVP_tls_cbc_copy_mac(uint8_t *out, unsigned md_size,
|
||||
const uint8_t *in, unsigned in_len,
|
||||
unsigned orig_len);
|
||||
|
||||
/* EVP_tls_cbc_record_digest_supported returns 1 iff |md| is a hash function
|
||||
* which EVP_tls_cbc_digest_record supports. */
|
||||
int EVP_tls_cbc_record_digest_supported(const EVP_MD *md);
|
||||
|
||||
/* EVP_tls_cbc_digest_record computes the MAC of a decrypted, padded TLS
|
||||
* record.
|
||||
*
|
||||
* md: the hash function used in the HMAC.
|
||||
* EVP_tls_cbc_record_digest_supported must return true for this hash.
|
||||
* md_out: the digest output. At most EVP_MAX_MD_SIZE bytes will be written.
|
||||
* md_out_size: the number of output bytes is written here.
|
||||
* header: the 13-byte, TLS record header.
|
||||
* data: the record data itself
|
||||
* data_plus_mac_size: the secret, reported length of the data and MAC
|
||||
* once the padding has been removed.
|
||||
* data_plus_mac_plus_padding_size: the public length of the whole
|
||||
* record, including padding.
|
||||
*
|
||||
* On entry: by virtue of having been through one of the remove_padding
|
||||
* functions, above, we know that data_plus_mac_size is large enough to contain
|
||||
* a padding byte and MAC. (If the padding was invalid, it might contain the
|
||||
* padding too. ) */
|
||||
int EVP_tls_cbc_digest_record(const EVP_MD *md, uint8_t *md_out,
|
||||
size_t *md_out_size, const uint8_t header[13],
|
||||
const uint8_t *data, size_t data_plus_mac_size,
|
||||
size_t data_plus_mac_plus_padding_size,
|
||||
const uint8_t *mac_secret,
|
||||
unsigned mac_secret_length);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
} /* extern C */
|
||||
#endif
|
||||
|
||||
#endif /* OPENSSL_HEADER_CIPHER_INTERNAL_H */
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,133 +0,0 @@
|
||||
# This is the example from
|
||||
# https://tools.ietf.org/html/draft-irtf-cfrg-gcmsiv-04#section-8
|
||||
|
||||
KEY: ee8e1ed9ff2540ae8f2ba9f50bc2f27c
|
||||
NONCE: 752abad3e0afb5f434dc4310
|
||||
IN: "Hello world"
|
||||
AD: "example"
|
||||
CT: 5d349ead175ef6b1def6fd
|
||||
TAG: 4fbcdeb7e4793f4a1d7e4faa70100af1
|
||||
|
||||
# Test vectors from
|
||||
# https://tools.ietf.org/html/draft-irtf-cfrg-gcmsiv-04#appendix-C
|
||||
|
||||
KEY: 01000000000000000000000000000000
|
||||
NONCE: 030000000000000000000000
|
||||
IN:
|
||||
AD:
|
||||
CT:
|
||||
TAG: dc20e2d83f25705bb49e439eca56de25
|
||||
|
||||
KEY: 01000000000000000000000000000000
|
||||
NONCE: 030000000000000000000000
|
||||
IN: 0100000000000000
|
||||
AD:
|
||||
CT: b5d839330ac7b786
|
||||
TAG: 578782fff6013b815b287c22493a364c
|
||||
|
||||
KEY: 01000000000000000000000000000000
|
||||
NONCE: 030000000000000000000000
|
||||
IN: 010000000000000000000000
|
||||
AD:
|
||||
CT: 7323ea61d05932260047d942
|
||||
TAG: a4978db357391a0bc4fdec8b0d106639
|
||||
|
||||
KEY: 01000000000000000000000000000000
|
||||
NONCE: 030000000000000000000000
|
||||
IN: 01000000000000000000000000000000
|
||||
AD:
|
||||
CT: 743f7c8077ab25f8624e2e948579cf77
|
||||
TAG: 303aaf90f6fe21199c6068577437a0c4
|
||||
|
||||
KEY: 01000000000000000000000000000000
|
||||
NONCE: 030000000000000000000000
|
||||
IN: 0100000000000000000000000000000002000000000000000000000000000000
|
||||
AD:
|
||||
CT: 84e07e62ba83a6585417245d7ec413a9fe427d6315c09b57ce45f2e3936a9445
|
||||
TAG: 1a8e45dcd4578c667cd86847bf6155ff
|
||||
|
||||
KEY: 01000000000000000000000000000000
|
||||
NONCE: 030000000000000000000000
|
||||
IN: 010000000000000000000000000000000200000000000000000000000000000003000000000000000000000000000000
|
||||
AD:
|
||||
CT: 3fd24ce1f5a67b75bf2351f181a475c7b800a5b4d3dcf70106b1eea82fa1d64df42bf7226122fa92e17a40eeaac1201b
|
||||
TAG: 5e6e311dbf395d35b0fe39c2714388f8
|
||||
|
||||
KEY: 01000000000000000000000000000000
|
||||
NONCE: 030000000000000000000000
|
||||
IN: 01000000000000000000000000000000020000000000000000000000000000000300000000000000000000000000000004000000000000000000000000000000
|
||||
AD:
|
||||
CT: 2433668f1058190f6d43e360f4f35cd8e475127cfca7028ea8ab5c20f7ab2af02516a2bdcbc08d521be37ff28c152bba36697f25b4cd169c6590d1dd39566d3f
|
||||
TAG: 8a263dd317aa88d56bdf3936dba75bb8
|
||||
|
||||
KEY: 01000000000000000000000000000000
|
||||
NONCE: 030000000000000000000000
|
||||
IN: 0200000000000000
|
||||
AD: 01
|
||||
CT: 1e6daba35669f427
|
||||
TAG: 3b0a1a2560969cdf790d99759abd1508
|
||||
|
||||
KEY: 01000000000000000000000000000000
|
||||
NONCE: 030000000000000000000000
|
||||
IN: 020000000000000000000000
|
||||
AD: 01
|
||||
CT: 296c7889fd99f41917f44620
|
||||
TAG: 08299c5102745aaa3a0c469fad9e075a
|
||||
|
||||
KEY: 01000000000000000000000000000000
|
||||
NONCE: 030000000000000000000000
|
||||
IN: 02000000000000000000000000000000
|
||||
AD: 01
|
||||
CT: e2b0c5da79a901c1745f700525cb335b
|
||||
TAG: 8f8936ec039e4e4bb97ebd8c4457441f
|
||||
|
||||
KEY: 01000000000000000000000000000000
|
||||
NONCE: 030000000000000000000000
|
||||
IN: 0200000000000000000000000000000003000000000000000000000000000000
|
||||
AD: 01
|
||||
CT: 620048ef3c1e73e57e02bb8562c416a319e73e4caac8e96a1ecb2933145a1d71
|
||||
TAG: e6af6a7f87287da059a71684ed3498e1
|
||||
|
||||
KEY: 01000000000000000000000000000000
|
||||
NONCE: 030000000000000000000000
|
||||
IN: 020000000000000000000000000000000300000000000000000000000000000004000000000000000000000000000000
|
||||
AD: 01
|
||||
CT: 50c8303ea93925d64090d07bd109dfd9515a5a33431019c17d93465999a8b0053201d723120a8562b838cdff25bf9d1e
|
||||
TAG: 6a8cc3865f76897c2e4b245cf31c51f2
|
||||
|
||||
KEY: 01000000000000000000000000000000
|
||||
NONCE: 030000000000000000000000
|
||||
IN: 02000000000000000000000000000000030000000000000000000000000000000400000000000000000000000000000005000000000000000000000000000000
|
||||
AD: 01
|
||||
CT: 2f5c64059db55ee0fb847ed513003746aca4e61c711b5de2e7a77ffd02da42feec601910d3467bb8b36ebbaebce5fba30d36c95f48a3e7980f0e7ac299332a80
|
||||
TAG: cdc46ae475563de037001ef84ae21744
|
||||
|
||||
KEY: 01000000000000000000000000000000
|
||||
NONCE: 030000000000000000000000
|
||||
IN: 02000000
|
||||
AD: 010000000000000000000000
|
||||
CT: a8fe3e87
|
||||
TAG: 07eb1f84fb28f8cb73de8e99e2f48a14
|
||||
|
||||
KEY: 01000000000000000000000000000000
|
||||
NONCE: 030000000000000000000000
|
||||
IN: 0300000000000000000000000000000004000000
|
||||
AD: 010000000000000000000000000000000200
|
||||
CT: 6bb0fecf5ded9b77f902c7d5da236a4391dd0297
|
||||
TAG: 24afc9805e976f451e6d87f6fe106514
|
||||
|
||||
KEY: 01000000000000000000000000000000
|
||||
NONCE: 030000000000000000000000
|
||||
IN: 030000000000000000000000000000000400
|
||||
AD: 0100000000000000000000000000000002000000
|
||||
CT: 44d0aaf6fb2f1f34add5e8064e83e12a2ada
|
||||
TAG: bff9b2ef00fb47920cc72a0c0f13b9fd
|
||||
|
||||
# Sample large random test vector.
|
||||
|
||||
KEY: d301238025c7ef4fe32fd20cc3ddb1dc
|
||||
NONCE: cab44881cefbcae419a122d6
|
||||
IN: 71356c78191cf4181cee0532d45d2d4fbbf62b9adf86b0643dd3735191283b1f9fd6a890029a4640294d0ffa9e18bf9da18cea164f87a01a376ec43163c5a612b125ca261e1eaedc03e3105b59e11bbbb8cc6c8247b3e5a0e55ad690c2a77b9f30e3b5202a187a6027097efa66ab0ba824dfc167ae51a581ca5e6c78d10a2e485c61404f0cf4bbb535e0b781ec1cf558e385d3f2d31334852015c402f77e7a4f69e45c88ca3b2950a0232971d80aec4b47c22d70ec2dfd058d5dad5ec4843df0173094053ccf265de85465d32dd36309798d88f7552e2b8a962d42e3744544e753516647fd0686860cdfa52c9a674a461df0a772f05cd814dcd80e8ebc871fa6994e045112178f98dea9f1fbcc3931bd5c3a6ba834ed083bdaad943e896c86c710ce59d49b36b882a24236e792e91351fc2b7a4385ed8d304b0c89e4785660822daecdf938fa237a97a95dec37d89cfc44c5964e31f4a257f996b628e8b0fded09d06e73b864200c7a8973dcc0e84f172940fa443c05dbe3a18e49b05c362adb57c7dcad2c31d3b2588e5931922c02f0eac0c3c7780213a978cd5a0ebcbaa4bdfb6873812e61c36b93d8f5d3b81db3f97f5a5207f274e4b1174f919defc2c63fe5cee5e9e2f3d91d7e726dfadb35bbb28ef01a625a97b502fe8a5ee56a5140668ca3429395440dc75dfb8212827ef9e5b7562f3f57dbf1a9d0e0fcbb2ceaddcbeea4cb2a8ef419cc12b767ed56712d19e431da3c6e48a21c3a5dba1b83f60e7a546000543946b24a8670684283736c230253873c39ed8d884967c2dacb365e55dc40c7f77787c1f050f16376c8220611ecec2887382b8fefa4b8627b0640038732f7ef0aad2877376b5256dd6f770a426749dd2f22f69684340e32548972be0feaab5dbbb0ae0b41460f6b483086b2d3d108e7f80a7cfa559dea483ea3c567cea8b16bb2f3eb29e9917be929e32571c7253b07d967a2c05d7f5b05c56f0dda6936a4d7d7b2e0ab877c99a9fedec49bc5058ffbaea034f7a5d493bf99cf3dea26d39076246e2a0f10d62b29799c04759b534a03b82e6cfff39872b07997a8de7d71ed87f0518581d15d34ccdbf66e6bbace42c56d7e4a7ef5e7e1462bd102fe104488bb4555676f04b4974ec436e6b05f7ea043641934bf02117079eb0323e213217662331d5dd310550a5db9a3a198770238e74da7d6667959956d736cd607c6c5c05eb279f077858101767a613024dfd31f50081ec482a2532276b2ccb272c1a5f00fc041dea0220ce8d51e5c73a7be649dfbaf1c4e75ab2e30cbfc61f3a83d866cc7e9318a4eca8ab9da2f4aea2c8a7e8b2f867adb134c3433f72edf471388fcd804ba316af409474197ade5a1f39d58a7378cd8bfca5a81588f43a05c09e4249a242cfb54a1c5ec70972dfabcbdccc61f305835dfa92a37d59148ad0b74d7
|
||||
AD: d1bbfb956faacbfd116bc473b3e0ae09feb224ec760f65b941d99a09eef82dcdd4f8111cfecf1ad4f02e0bdc3a137b9095f922dc3a80d98282827066c201779af4f4267364dcb3eee26a8c9e885b835e7836666dedce8dc912aa328c56bafa3f5746a5c7304cb6805e895885dc520edcea76739db2b426e93ef404b406ede2d57f0131ad6cb1049b18e0bff1bea181b57a3b942b55348a7d2afb056e90f421f5e281c9c3ada60c5891a2e518981704d92c5712991b31a620a3d53811b971469d4fa86e32de261a4679671cfd983c56fe037e9232f06a53aa1eeb2f61caa4f8c1079679ee9fa581ee5eb49842290152655c15bad483b96340a5f1fd67368fda29
|
||||
CT: 8dd19cbf232354e78032baaafd52903569381a29110fe1a6bdeeb539149d69e35f1d8efa09c029c21514ce1a040371714b317921228d8718bb979378cfbb53e60b16ba6ffbdedfa0283d9c48fdef183aa6000d05aa1bcf76f478a6de9356726f1645a681ec9cd84716403e354f38b5364f5ca290291c965b82fe4c0d3085d853ccb0588e4c815214e895b46fc2758747559920e0d137d105419e2856d0e0e5bcbb6f7d3d6055bbbcdd29c7a70fc80a00392bd27174c0bc806adfae08e32b308ce8128e4bbae574e96daea0d3676c7ee259bf2a1ee0af0f474401795794cb51d508db5ee02d346a5019a5dcda7532317a41a7147af946d56cb1dcbd53e28feadbd9af9cd3eb96c7bff0611c2f387d95f8caf8b3ca59d02020340630406e597d665b2d2193635f157c51f1b19a1cf4349d1ef227f62812d6cdb0c7dae87647f1ac28c79d643ac0d06781ccc24d626c44e0a3b7a55e3a81f30118703d489b93dd01f94ecae0ac42e1eb7e937f67a38dafe9ec0c5d2bf846acd1536011c02a63153c9e4c0bd4e467e5671e52507a34e3a8dc6de18eb967a54cf63bc049e0c7fe89988c394959ef80f8c23bd93aef9a150ae33a245fe8b6db955193632118e1adfea566620b6dd8ac46a16f86651a8d34719128a07c63123eda805602ce923eb0b945886bd73adfe08beb77b50cbc6fb023f41355d5f1e16f289b9ad86ae89e35c978dfe8b8356f80bb809fe9274553dc094e96d865ee1cad1de31e4c838e5b5564b581369e8ff719e1dd84c3465bff3981bbafc874bb206b5e9f58d175c292613ac4005bdfafd411acda8c94d64b58462d2612b2877c9284b1a88fd55631abe6fa17a7fecf3635256c3e09fe3b7aaf032a411e8b9645def45219de48d58aeec6e239ee211de18051a2a5175a265ce1bab462c7a35c46590f6e1fa543f0ffd3777c564dba9a1bd1124b96fc2d1e7e81e51ecc83f7c6f2ee02b09962bd5f2744e54d58592336515f39a4ccccbfaa8d829259abd0030da76648dab078574638c730bd9c32f8179592029faa9f19adde63fd7e2d671d1c22cbadd8d28d4dbe8d098fa5fbb593884830fe6bb4afd89bd1143f77d194938c71f01fa3323cc23f18bdd486bc7a468bfa6fc0e9bd198ac4fb572f1d94fc3ff7e4860621929d39967e1baf493132188d6978bba043b2264ded093709a224af7358d5aae09667a1b6533e714fd9ab5157e201d7d14e7f559c1e0709faadad5c18ec7144faea92b134f9ac48a97a13d98e4fe0b4c4a66daa0b6adb23d2d17be82da4f590caf6034b2f0c3a846a2740339ec24223e1c024a3955f54b87358b62247afeca011d4830b0e23174965aac60b7f5517f11b23dadc06e4e72e4d89d0f5764e804e840a495d8352dc0bf22ff454a118db981224b73632eeebe5496a2c5a43cf69af0a79e84e1d12398c8024
|
||||
TAG: ae3f5d2b7ff538343964febbcd9e919b
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,123 +0,0 @@
|
||||
# Test vectors from
|
||||
# https://tools.ietf.org/html/draft-irtf-cfrg-gcmsiv-04#appendix-C
|
||||
|
||||
KEY: 0100000000000000000000000000000000000000000000000000000000000000
|
||||
NONCE: 030000000000000000000000
|
||||
IN:
|
||||
AD:
|
||||
CT:
|
||||
TAG: 07f5f4169bbf55a8400cd47ea6fd400f
|
||||
|
||||
KEY: 0100000000000000000000000000000000000000000000000000000000000000
|
||||
NONCE: 030000000000000000000000
|
||||
IN: 0100000000000000
|
||||
AD:
|
||||
CT: c2ef328e5c71c83b
|
||||
TAG: 843122130f7364b761e0b97427e3df28
|
||||
|
||||
KEY: 0100000000000000000000000000000000000000000000000000000000000000
|
||||
NONCE: 030000000000000000000000
|
||||
IN: 010000000000000000000000
|
||||
AD:
|
||||
CT: 9aab2aeb3faa0a34aea8e2b1
|
||||
TAG: 8ca50da9ae6559e48fd10f6e5c9ca17e
|
||||
|
||||
KEY: 0100000000000000000000000000000000000000000000000000000000000000
|
||||
NONCE: 030000000000000000000000
|
||||
IN: 01000000000000000000000000000000
|
||||
AD:
|
||||
CT: 85a01b63025ba19b7fd3ddfc033b3e76
|
||||
TAG: c9eac6fa700942702e90862383c6c366
|
||||
|
||||
KEY: 0100000000000000000000000000000000000000000000000000000000000000
|
||||
NONCE: 030000000000000000000000
|
||||
IN: 0100000000000000000000000000000002000000000000000000000000000000
|
||||
AD:
|
||||
CT: 4a6a9db4c8c6549201b9edb53006cba821ec9cf850948a7c86c68ac7539d027f
|
||||
TAG: e819e63abcd020b006a976397632eb5d
|
||||
|
||||
KEY: 0100000000000000000000000000000000000000000000000000000000000000
|
||||
NONCE: 030000000000000000000000
|
||||
IN: 010000000000000000000000000000000200000000000000000000000000000003000000000000000000000000000000
|
||||
AD:
|
||||
CT: c00d121893a9fa603f48ccc1ca3c57ce7499245ea0046db16c53c7c66fe717e39cf6c748837b61f6ee3adcee17534ed5
|
||||
TAG: 790bc96880a99ba804bd12c0e6a22cc4
|
||||
|
||||
KEY: 0100000000000000000000000000000000000000000000000000000000000000
|
||||
NONCE: 030000000000000000000000
|
||||
IN: 01000000000000000000000000000000020000000000000000000000000000000300000000000000000000000000000004000000000000000000000000000000
|
||||
AD:
|
||||
CT: c2d5160a1f8683834910acdafc41fbb1632d4a353e8b905ec9a5499ac34f96c7e1049eb080883891a4db8caaa1f99dd004d80487540735234e3744512c6f90ce
|
||||
TAG: 112864c269fc0d9d88c61fa47e39aa08
|
||||
|
||||
KEY: 0100000000000000000000000000000000000000000000000000000000000000
|
||||
NONCE: 030000000000000000000000
|
||||
IN: 0200000000000000
|
||||
AD: 01
|
||||
CT: 1de22967237a8132
|
||||
TAG: 91213f267e3b452f02d01ae33e4ec854
|
||||
|
||||
KEY: 0100000000000000000000000000000000000000000000000000000000000000
|
||||
NONCE: 030000000000000000000000
|
||||
IN: 020000000000000000000000
|
||||
AD: 01
|
||||
CT: 163d6f9cc1b346cd453a2e4c
|
||||
TAG: c1a4a19ae800941ccdc57cc8413c277f
|
||||
|
||||
KEY: 0100000000000000000000000000000000000000000000000000000000000000
|
||||
NONCE: 030000000000000000000000
|
||||
IN: 02000000000000000000000000000000
|
||||
AD: 01
|
||||
CT: c91545823cc24f17dbb0e9e807d5ec17
|
||||
TAG: b292d28ff61189e8e49f3875ef91aff7
|
||||
|
||||
KEY: 0100000000000000000000000000000000000000000000000000000000000000
|
||||
NONCE: 030000000000000000000000
|
||||
IN: 0200000000000000000000000000000003000000000000000000000000000000
|
||||
AD: 01
|
||||
CT: 07dad364bfc2b9da89116d7bef6daaaf6f255510aa654f920ac81b94e8bad365
|
||||
TAG: aea1bad12702e1965604374aab96dbbc
|
||||
|
||||
KEY: 0100000000000000000000000000000000000000000000000000000000000000
|
||||
NONCE: 030000000000000000000000
|
||||
IN: 020000000000000000000000000000000300000000000000000000000000000004000000000000000000000000000000
|
||||
AD: 01
|
||||
CT: c67a1f0f567a5198aa1fcc8e3f21314336f7f51ca8b1af61feac35a86416fa47fbca3b5f749cdf564527f2314f42fe25
|
||||
TAG: 03332742b228c647173616cfd44c54eb
|
||||
|
||||
KEY: 0100000000000000000000000000000000000000000000000000000000000000
|
||||
NONCE: 030000000000000000000000
|
||||
IN: 02000000000000000000000000000000030000000000000000000000000000000400000000000000000000000000000005000000000000000000000000000000
|
||||
AD: 01
|
||||
CT: 67fd45e126bfb9a79930c43aad2d36967d3f0e4d217c1e551f59727870beefc98cb933a8fce9de887b1e40799988db1fc3f91880ed405b2dd298318858467c89
|
||||
TAG: 5bde0285037c5de81e5b570a049b62a0
|
||||
|
||||
KEY: 0100000000000000000000000000000000000000000000000000000000000000
|
||||
NONCE: 030000000000000000000000
|
||||
IN: 02000000
|
||||
AD: 010000000000000000000000
|
||||
CT: 22b3f4cd
|
||||
TAG: 1835e517741dfddccfa07fa4661b74cf
|
||||
|
||||
KEY: 0100000000000000000000000000000000000000000000000000000000000000
|
||||
NONCE: 030000000000000000000000
|
||||
IN: 0300000000000000000000000000000004000000
|
||||
AD: 010000000000000000000000000000000200
|
||||
CT: 43dd0163cdb48f9fe3212bf61b201976067f342b
|
||||
TAG: b879ad976d8242acc188ab59cabfe307
|
||||
|
||||
KEY: 0100000000000000000000000000000000000000000000000000000000000000
|
||||
NONCE: 030000000000000000000000
|
||||
IN: 030000000000000000000000000000000400
|
||||
AD: 0100000000000000000000000000000002000000
|
||||
CT: 462401724b5ce6588d5a54aae5375513a075
|
||||
TAG: cfcdf5042112aa29685c912fc2056543
|
||||
|
||||
# Sample large random test vector.
|
||||
|
||||
KEY: 9f646d6337565c689c9ec7627ad95c26a2df7d3a36fba9f1265c607458bbb1b6
|
||||
NONCE: 336bb4bb0c03e8c87efe3b5b
|
||||
IN: ec257ff779f7cb246a38462562e508b14adbd3ff33041b94aab6f10a3e8b7fe16738f12afa470c9100924b211a728f90ba6d2260b4d451d3f4701d72b8a8cd53921f65e8aa7b6bd3995fef3cf6db60d1e2927c9012ea2a62af3a50fdada2262f8f02d9651d542e3856210af36def3c6d1b712de4dd34c63a09a6d2928019c62a7253cb47a9ed056d7435d723809768192c7df2768aa4b9ab247e1a522fa58532c7d785d2236f92fc1f4ab621023f5e5af084fe41584d136cec5ce33472f85c4dc045e70bbd5b6781c394b4b2872b3734879de37454a5351d272a84301ef5df121c0ac70de6f375b7bb185730baaa7f9b4ab093d66e34e799e3abd94d03b6c344a82968a07ed8b6fea37e5c2275b8ad40faa040558ea8636af91f42be30af2c61c34c50459e04ed93998da10c2d7cb75f4b18fa027fbd7d5f0e0b830784fc530b0df84b253690649dba92671373e43773a324b81624298a5006c9083adf09ff35ab7b098b67e40c65888f6027eb741637afc646b6769c70b594c771fb94049d4f4e74e0c9967689716d8d37405687a7dea0527500df90dee256e496f251892023dc729d42cbfb4f2514cdc177cb427d6d46493770f91744b9c173ddae6b6baf7e2e95dc6dd268e2b89510deeb2fa5aaa108cf4b7da8a2af7a6cb18c32ceec6be8d2ec734bfeffe25464aa0cbcaaea9508c92ffbb1973d7cdc6118845df7d9386da2fac4e36bddb37d01bbd47d0bcb793850865a4ee08836a72281ff1bda146017145962bbbdd486e6e3a457d3f3c0e05a7cd3514e4aaec85730a39fc8ffe8904e1009d565d919b64e388988db05f90599649699a33f7620df75be25c0c45e1f3829ca38df1343f93dd1fe5b8f05584828f9bcc61c474737ddef2ad0b0436cf303ad2f404785a6db7314e9af2e0eaa68fffcd9dac3a905709d31a259c1e5b808c2fe036ffacb4ce0ca072835815e9f232e29c193e8519d0cb4cf4e8b1f9145c13211232d082229bd80efadd0e215e30873233f60a45441295396c03916d2c44cdc30e8c3650b4045b656d530372414723d1739fe353f4124b80d78d0a170925044b225139e75b4a774262656c72ad4cce99725d505871e3c7e01fb45e5f9f36b68f6ed7974f698967fbabe57b3143ed43d7e6c9cf253b16e8758267598f687e69c217194c5ea1bbbae73757d28d109582129dfc4777a27fafb3a8c3f64c5db209e4ce06099dd0ef3ab5c123a6435d2b0603b102e9b88398413373c53d2252620b8bd7293abe35e46be0b2f828ecfe573312dd85444d32fd5d18a39295865d367aec0d51193cfe8284670f3f1febdf64e34bb6f3ecb2efd0c43f66234ff01dee3465d2fb1d9ce87f3ef7f8f57674fb269bbe8f3e2001ef6b610eed4a2d0d2e2c1b696e4e32084fe4c340612aa13636e223dd758cd765e7864b96ba787d16432bd3c
|
||||
AD: 3d186bc3d38b19b41e8c039f5417be09358ad8743cb26b6fefe19a9752901a9bc18a6ed325ec307861bd0fa333a9b0d156dbf30a84f11b72d9b74000d1690f317c04598b1930ef6df873fd9c098abdb7e92eb82d9e5675518365af68a990477f2b70fa5514ec5f5010b5ac0d00fa6d848c40c49aed54b526cd8586bb783bcac299b8c0e96853c242d7c34479bca18aff6d55fbef52c735c41a363d68452304125bea529d235e09cc861198bd292ee63ea1387f859eda363f664c3952aa4fae135cbc0d37ae89f2f34cf1a5b6a685ebbfbac18209e0ea38aadd71a6c16163b5676e84b4bc539c4b1079553a6765726cc8064489c8cbfd3c0999021d70b4c0aea0
|
||||
CT: 17bb864ba0458a63fa51ec47259f0e22a9aa387bff7774f3badc55e13748c96f4d0463d73a29d70140f384aba50f9efcd5d0fcbfd1b0b4b16226993aa00260fc1f0a0a28b4a9a19acd9d966920a56a95cacee547a0b3b1d6a752e575a10101d3ba91d59a10ac9eac7367caa1e3a5ad7173d149bd69f97ee1e6782e05f14d9434716bd103ca2e48337bb1cc68d54f31d75244a53cf1d2e47f55da7fc2b80b8eea4110c1887b157530cafa2519bef54f7f4641a8bb5bf2a7f3ea50be71aa8def7d6244c49d2d11de0e08058d08e8619aa3cedcfed1850651585e38489b9b1c7a8aad5ccb3fd380ca2745c5b8b530e6c6ce4fdb7acc8de1543d0364a96d6dac08ffe4474a4f34a96a47c4a7d5db27997963546350e28150e34f81dc6d1d354e867d5e3850f285da5890906f76471f8133da4899ee9b6774da38860e7d8de09edb782eefbbcbebfc2b61aaaae92e0f576a789b8ae4c40359e2dc69e352dc1631a7b791b41788b13b228585301e035c134f3e3a51a7622aead20191445437a9283cd03c6fd9cf128006f96eaaebfa4d71476efafef719189aefdee20d14fb5fb2d0a783ec9894edf3e937b405b7eec3c51649bba3c73a2d94e1b3cb059b6d587d9ee2714c813345f5b29852bec2422490edaf8a7423f2481c8c65497db9711143cff07c0a9889b786ac3e4def8065c8417fd56a91b20a27fb6e5bf8a188039fd51ccfb8be365b1a9f4abbf05135c66928a449aeb6110a70894edbe7e00c2111ff7bf718781965f6e49b758397036b9df6ef77f5aa005d98ff9d61612dc70fe0794e6aa9d3e78a86a3d42f5048a0f6ece5d1264eeb88c94ae529c53933b977dceb41da1b0299fd89ef4b94f66cafb67d0165a9e4210b6958f1ee66d30f7be6643970ccd9df3b11ed29580c5352cbfa3bc8cdd11454282de0b43ad748366948871d4862167fa42d6ed8de023009c9944149227f88e135c53bd50f6ea0727e7cf30ec5bf68ec951d5713fa79175e6aa5ccfe634594497e82b57f7efac8e7293d40ca2af0b63be2aa09d8b97edb7002152220ff96c620f2ab9463f1a1f0517a5df03a47842480f06835377506dd50595946a1bbccb0ef299335fe8b442aca0f900f7068d3f4c06b1c7da8c59c22ab6d1489b474c3e346f67d4a4f0b895b6c45a432bca80f95d34fb2c12dd60c4fe0cc1ac1f4e826f353ddc1ec9072554ac2259c572072d309135d3fbf879288c4cebe756663ebab72fe2078c661f3feb5ed7ef398c2f9d69dd289a835e5251d916e733b3f981714dc3e28ef8fc17b230f7aaa8ed11a99d81a7238f9041704c66b1ae02ef7d4a14bf94b5713e6a5f16718e2b2152e4e8a5f9d673dbfb14ce0b032aa7fc9e264f9002a7f955f7644cf16deede930ec209171472f2cdbabc65632220928a64eb29bfaf411b63b58a30a98b1a47a54c007bbd6
|
||||
TAG: f2d188b9ec069b81793a841cfdcd1f88
|
||||
@@ -1,524 +0,0 @@
|
||||
KEY: 9a97f65b9b4c721b960a672145fca8d4e32e67f9111ea979ce9c4826806aeee6
|
||||
NONCE: 3de9c0da2bd7f91e
|
||||
IN: ""
|
||||
AD: ""
|
||||
CT: ""
|
||||
TAG: 5a6e21f4ba6dbee57380e79e79c30def
|
||||
|
||||
KEY: bcb2639bf989c6251b29bf38d39a9bdce7c55f4b2ac12a39c8a37b5d0a5cc2b5
|
||||
NONCE: 1e8b4c510f5ca083
|
||||
IN: 8c8419bc27
|
||||
AD: 34ab88c265
|
||||
CT: 1a7c2f33f5
|
||||
TAG: 2875c659d0f2808de3a40027feff91a4
|
||||
|
||||
KEY: 4290bcb154173531f314af57f3be3b5006da371ece272afa1b5dbdd1100a1007
|
||||
NONCE: cd7cf67be39c794a
|
||||
IN: 86d09974840bded2a5ca
|
||||
AD: 87e229d4500845a079c0
|
||||
CT: e3e446f7ede9a19b62a4
|
||||
TAG: 677dabf4e3d24b876bb284753896e1d6
|
||||
|
||||
KEY: 422a5355b56dcf2b436aa8152858106a88d9ba23cdfe087b5e74e817a52388b3
|
||||
NONCE: 1d12d6d91848f2ea
|
||||
IN: 537a645387f22d6f6dbbea568d3feb
|
||||
AD: bef267c99aec8af56bc238612bfea6
|
||||
CT: 281a366705c5a24b94e56146681e44
|
||||
TAG: 38f2b8ee3be44abba3c010d9cab6e042
|
||||
|
||||
KEY: ec7b864a078c3d05d970b6ea3ba6d33d6bb73dfa64c622a4727a96ede876f685
|
||||
NONCE: 2bca0e59e39508d3
|
||||
IN: b76733895c871edd728a45ed1a21f15a9597d49d
|
||||
AD: cc1243ea54272db602fb0853c8e7027c56338b6c
|
||||
CT: 1fb9b2958fce47a5cada9d895fbb0c00d3569858
|
||||
TAG: 042ad5042c89ebc1aad57d3fb703d314
|
||||
|
||||
KEY: 2c4c0fdb611df2d4d5e7898c6af0022795364adb8749155e2c68776a090e7d5c
|
||||
NONCE: 13ce7382734c4a71
|
||||
IN: 0dc6ff21a346e1337dd0db81d8f7d9f6fd1864418b98aadcdb
|
||||
AD: 0115edcb176ab8bfa947d1f7c3a86a845d310bf6706c59a8f9
|
||||
CT: dad65e4244a1a17ce59d88b00af4f7434bd7830ffdd4c5558f
|
||||
TAG: ac1437b45d8eacf9c0fe547c84fb82a2
|
||||
|
||||
KEY: c66e89fbab01208f6a60847f4f34b38d27b554c119cf8d9e0b118aa7266ab865
|
||||
NONCE: 5d9856060c54ab06
|
||||
IN: f9e3e9b5ed07b2080db8c1ffc37e4a6cb3cd544608921e18610d00b17c6e
|
||||
AD: 85c112a1efe0a20ef3a550526a7afbc98f6367ebbede4e703099abd78f51
|
||||
CT: b5cc754f6dd19ef2d66f90e6bc9a322ddf216ef248cbe76b5ab6dd53bc36
|
||||
TAG: 6dd98710d8a889dceea0d0a936f98617
|
||||
|
||||
KEY: a8b9766f404dea8cf7d7dfaf5822f53df9ccd092e332a57f007b301b507d5e14
|
||||
NONCE: c7f2f7a233104a2d
|
||||
IN: 4d6faeaee39179a7c892faae3719656cc614c7e6ecd8fcb570a3b82c4dace969090338
|
||||
AD: c6d83b6a56408a356e68d0494d4eff150530b09551d008373d6dee2b8d6b5619d67fdb
|
||||
CT: a15443f083316eef627a371f4c9ac654d0dd75255d8a303125e9f51af4233ff4ceb7fe
|
||||
TAG: 52504e880f6792a60708cc6db72eae42
|
||||
|
||||
KEY: 5e8d0e5f1467f7a750c55144d0c670f7d91075f386795b230c9bf1c04ba250bc
|
||||
NONCE: 88049f44ba61b88f
|
||||
IN: 51a1eebcc348e0582196a0bce16ed1f8ac2e91c3e8a690e04a9f4b5cf63313d7ad08d1efbff85c89
|
||||
AD: 5d09bf0be90026f9fc51f73418d6d864b6d197ea030b3de072bd2c2f5cab5860a342abbd29dba9dc
|
||||
CT: 35aa4bd4537aa611fd7578fc227df50ebcb00c692a1cf6f02e50ed9270bd93af3bc68f4c75b96638
|
||||
TAG: ccea1cbbc83944cc66df4dbf6fb7fc46
|
||||
|
||||
KEY: 21a9f07ec891d488805e9b92bb1b2286f3f0410c323b07fee1dc6f7379e22e48
|
||||
NONCE: 066215be6567377a
|
||||
IN: c1b0affaf2b8d7ef51cca9aacf7969f92f928c2e3cc7db2e15f47ee1f65023910d09f209d007b7436ee898133d
|
||||
AD: dfdfdf4d3a68b47ad0d48828dc17b2585da9c81c3a8d71d826b5fa8020fee002397e91fc9658e9d61d728b93eb
|
||||
CT: 8ff4ceb600e7d45696d02467f8e30df0d33864a040a41ffb9e4c2da09b92e88b6f6b850e9f7258d827b9aaf346
|
||||
TAG: 4eeddc99784011f0758ba5ebfba61827
|
||||
|
||||
KEY: 54c93db9aa0e00d10b45041c7a7e41ee9f90ab78ae4c1bba18d673c3b370abde
|
||||
NONCE: 3f2d44e7b352360f
|
||||
IN: 1241e7d6fbe5eef5d8af9c2fb8b516e0f1dd49aa4ebe5491205194fe5aea3704efaf30d392f44cc99e0925b84460d4873344
|
||||
AD: f1d1b08dd6fe96c46578c1d1ad38881840b10cb5eae41e5f05fe5287223fa72242aea48cb374a80be937b541f9381efa66bb
|
||||
CT: 027b86865b80b4c4da823a7d3dbcf5845bf57d58ee334eb357e82369cc628979e2947830d9d4817efd3d0bc4779f0b388943
|
||||
TAG: 4303fa0174ac2b9916bf89c593baee37
|
||||
|
||||
KEY: 808e0e73e9bcd274d4c6f65df2fe957822a602f039d4752616ba29a28926ef4a
|
||||
NONCE: 1b9cd73d2fc3cb8e
|
||||
IN: 3436c7b5be2394af7e88320c82326a6db37887ff9de41961c7d654dd22dd1f7d40444d48f5c663b86ff41f3e15b5c8ca1337f97635858f
|
||||
AD: d57cfbe5f2538044282e53b2f0bb4e86ea2233041fb36adb8338ded092148f8c2e894ef8766a7ec2dd02c6ac5dbab0c3703c5e9119e37c
|
||||
CT: 9b950b3caf7d25eaf5fca6fa3fe12ed077d80dcd5579851233c766bb8bb613ec91d925a939bb52fb88d5eda803cfe2a8cda2e055b962fd
|
||||
TAG: 6bf5b718f5bbe1395a5fdfcbbef752f5
|
||||
|
||||
KEY: 4adfe1a26c5636536cd7cb72aa5bded0b1aa64487ad0e4078f311e8782768e97
|
||||
NONCE: d69e54badec11560
|
||||
IN: 19b3f9411ce875fcb684cbdc07938c4c1347e164f9640d37b22f975b4b9a373c4302ae0e7dfdeba1e0d00ced446e338f4c5bc01b4becef5115825276
|
||||
AD: bda1b0f6c2f4eb8121dcbd2eebd91a03ae1d6e0523b9b6f34b6f16ceca0d086654fb0552bfd5c8e1887730e1449ea02d7f647ae835bc2dab4bbc65b9
|
||||
CT: ea765a829d961e08bacaed801237ef4067df38ad3737b7c6de4db587a102a86fc4abbaabea0ee97c95ca7f571c7bab6f38cbae60cd6e6a4ce3c7a320
|
||||
TAG: b425cdf10cd0123a7e64b347c6b4b1f0
|
||||
|
||||
KEY: eb3db86c14b7cc2e494345d0dfb4841bbd3aa1e2bc640cca0c6c405520685639
|
||||
NONCE: 88b54b28d6da8c81
|
||||
IN: f75c0a357271430b1ecff07a307b6c29325c6e66935046704a19845e629f87a9e3b8aa6c1df55dd426a487d533bb333e46f0d3418464ac1bef059231f8e87e6284
|
||||
AD: 34b08bb0df821c573dcb56f5b8b4a9920465067f3b5bf3e3254ea1da1a7fc9847fd38bdfe6b30927945263a91fa288c7cf1bee0fddb0fadf5948c5d83eb4623575
|
||||
CT: 146ec84f5dc1c9fe9de3307a9182dbaa75965bf85f5e64563e68d039a5b659aa8863b89228edb93ff3d8c3323ab0d03300476aa4aca206d4626a6b269b2078912d
|
||||
TAG: 0058a8dff32c29935c62210c359bd281
|
||||
|
||||
KEY: dd5b49b5953e04d926d664da3b65ebcffbbf06abbe93a3819dfc1abbecbaab13
|
||||
NONCE: c5c8009459b9e31a
|
||||
IN: f21f6706a4dc33a361362c214defd56d353bcb29811e5819ab3c5c2c13950c7aa0000b9d1fe69bb46454514dcce88a4a5eda097c281b81e51d6a4dba47c80326ba6cea8e2bab
|
||||
AD: fe6f4cbb00794adea59e9de8b03c7fdf482e46f6c47a35f96997669c735ed5e729a49416b42468777e6a8d7aa173c18b8177418ded600124a98cbb65489f9c24a04f1e7127ce
|
||||
CT: 911ead61b2aa81d00c5eff53aeea3ab713709ed571765890d558fb59d3993b45f598a39e5eff4be844c4d4bd1ef9622e60412b21140007d54dcf31b2c0e3e98cf33a00fd27f0
|
||||
TAG: d38d672665e2c8c4a07954b10ecff7d9
|
||||
|
||||
KEY: 3b319e40148a67dc0bb19271d9272b327bc5eee087173d3d134ad56c8c7dc020
|
||||
NONCE: ce5cf6fef84d0010
|
||||
IN: 27b5627b17a2de31ad00fc2ecb347da0a399bb75cc6eadd4d6ee02de8fbd6a2168d4763ba9368ba982e97a2db8126df0343cdad06d2bc7d7e12eec731d130f8b8745c1954bfd1d717b4ea2
|
||||
AD: a026b6638f2939ec9cc28d935fb7113157f3b5b7e26c12f8f25b36412b0cd560b7f11b62788a76bd171342e2ae858bcecb8266ff8482bbaed593afe818b9829e05e8e2b281ae7799580142
|
||||
CT: 368fb69892447b75778f1c5236e1e9d5d89255c3d68d565a5bba4f524d6ad27de13087f301e2ef4c08f5e2c6128b1d3e26de845c4ac4869e4c8bd8858ad0d26dec3b5d61a9e3666a3911ba
|
||||
TAG: 2e70564c3999c448d92cc6df29d095c4
|
||||
|
||||
KEY: 43bf97407a82d0f684bb85342380d66b85fcc81c3e22f1c0d972cd5bfdf407f4
|
||||
NONCE: 8b6ba494c540fba4
|
||||
IN: 4b4c7e292a357f56fdf567c32fc0f33608110d7ce5c69112987d7b5a0bd46d8627a721b0aed070b54ea9726084188c518cba829f3920365afc9382c6a5eb0dd332b84612366735be2479b63c9efc7ff5
|
||||
AD: 1e0acf4070e8d6758b60d81b6d289a4ecdc30e3de4f9090c13691d5b93d5bbcef984f90956de53c5cf44be6c70440661fa58e65dec2734ff51d6d03f57bddda1f47807247e3194e2f7ddd5f3cafd250f
|
||||
CT: d0076c88ad4bc12d77eb8ae8d9b5bf3a2c5888a8d4c15297b38ece5d64f673191dc81547240a0cbe066c9c563f5c3424809971b5a07dcc70b107305561ce85aecb0b0ea0e8b4ff4d1e4f84836955a945
|
||||
TAG: 75c9347425b459af6d99b17345c61ff7
|
||||
|
||||
KEY: 12fc0bc94104ed8150bde1e56856ce3c57cd1cf633954d22552140e1f4e7c65d
|
||||
NONCE: d3875d1b6c808353
|
||||
IN: 24592082d6e73eb65c409b26ceae032e57f6877514947fc45eb007b8a6034494dde5563ac586ea081dc12fa6cda32266be858e4748be40bb20f71320711bf84c3f0e2783a63ad6e25a63b44c373a99af845cdf452c
|
||||
AD: b8be08463e84a909d071f5ff87213391b7da889dc56fd2f1e3cf86a0a03e2c8eaa2f539bf73f90f5298c26f27ef4a673a12784833acb4d0861562142c974ee37b09ae7708a19f14d1ad8c402bd1ecf5ea280fab280
|
||||
CT: 9d9ae6328711fb897a88462d20b8aa1b278134cdf7b23e1f1c809fa408b68a7bfc2be61a790008edaa98823381f45ae65f71042689d88acfa5f63332f0fba737c4772c972eba266640056452903d6522cefd3f264e
|
||||
TAG: e9c982d4ade7397bcfaa1e4c5a6cd578
|
||||
|
||||
KEY: 7b6300f7dc21c9fddeaa71f439d53b553a7bf3e69ff515b5cb6495d652a0f99c
|
||||
NONCE: 40b32e3fdc646453
|
||||
IN: 572f60d98c8becc8ba80dd6b8d2d0f7b7bbfd7e4abc235f374abd44d9035c7650a79d1dd545fa2f6fb0b5eba271779913e5c5eb450528e4128909a96d11a652bf3f7ae9d0d17adbf612ec9ca32e73ef6e87d7f4e21fe3412ce14
|
||||
AD: 9ff377545a35cf1bfb77c734ad900c703aee6c3174fdb3736664863036a3a9d09163c2992f093e2408911b8751f001e493decc41e4eeeed04f698b6daed48452a7e1a74ec3b4f3dcf2151ca249fa568aa084c8428a41f20be5fd
|
||||
CT: 229da76844426639e2fd3ef253a195e0a93f08452ba37219b6773f103134f3f87b1345f9b4bf8cfc11277c311780a2b6e19a363b6ac2efe6c4cc54a39b144e29c94b9ebbde6fd094c30f59d1b770ebf9fcad2a5c695dc003bf51
|
||||
TAG: b72acab50131a29558d56ae7b9d48e4e
|
||||
|
||||
KEY: 4aeb62f024e187606ee7cc9f5865c391c43df1963f459c87ba00e44bb163a866
|
||||
NONCE: 9559bd08718b75af
|
||||
IN: c5d586ceece6f41812c969bcf1e727fe6ff8d1ae8c8c52367c612caa7cdf50e0662f5dffc5ea7d3cc39400dfe3dc1897905f6490fd7747b5f5f9842739c67d07ce7c339a5b3997a7fb4cd0d8e4817ff8916b251c11ef919167f858e41504b9
|
||||
AD: 51f5b503b73a5de8b96534c2a3f2d859ece0bd063ea6dfa486a7eec99f6c020983f7148cccb86202cf9685cc1cc266930f04e536ad8bc26094252baa4606d883bd2aeed6b430152202e9b6cc797ff24fc365315ed67391374c1357c9a845f2
|
||||
CT: 252ea42b6e5740306816974a4fe67b66e793ebe0914778ef485d55288eb6c9c45fa34ac853dc7a39252520514c3cb34c72b973b14b32bc257687d398f36f64cc2a668faffa7305ab240171343b5f9f49b6c2197e4fbe187b10540d7cdcfa37
|
||||
TAG: 711ff33ef8d2b067a1b85c64f32f1814
|
||||
|
||||
KEY: 9a19e72f005cae1ae78b8e350d7aabe59fc8845999e8c52fad545b942c225eaf
|
||||
NONCE: d9dae2ea8d2ffc31
|
||||
IN: 2110378d856ded07eb2be8e8f43308e0c75bc8a3fcc7b1773b0725b7de49f6a166c4528e64120bdf7c9776615d3ce6feeb03de964a7b919206a77392f80437faceb6745845cafc166e1c13b68e70ca2a1d00c71737b8fcbbbd50902565c32159e05fcd23
|
||||
AD: 1cd73b72c4e103afbefd7c777e0480f3f5e68c60b85bd2e71ef5caebb175d7fc6535d39f38f92c24f2eb0fe97d878ed3d5967c0bb4394a5d41f7d34cda6e1523d3848f049cde554a7d31e1afeab5d3e6150f85858335cbd28c8a7f87d528058df50eea06
|
||||
CT: 5f009fbce4ec8e4ca9d8d42258b1a3e4e920b2fbad33d5e9f07557d9595e841025193b521ba440110dd83958e8ee30219d952b418e98a6c624894aa248aedc0678f2d263e7bfaf54ca379fef6c5d2f7ac422ea4b4369408b82d6225a7a2cf9a9f46fd4ef
|
||||
TAG: aa0a5fa7d3cf717a4704a59973b1cd15
|
||||
|
||||
KEY: ba1d0b3329ecc009f1da0fab4c854b00ad944870fdca561838e38bad364da507
|
||||
NONCE: 8a81c92b37221f2f
|
||||
IN: 6289944ffa3ccea4bf25cd601b271f64e6deb0eba77d65efb4d69ca93e01996e4727168b6f74f3ccf17bd44715f23ceb8fc030c0e035e77f53263db025021fd2d04b87a1b54b12229c5e860481452a80a125cb0693a2ba1b47e28ee7cbaf9e683c178232c7f6d34f97
|
||||
AD: e57883961b8d041d9b9eeaddcfd61fa9f59213f66571fadffffdd1498b9b014f1ef2e7e56c3044d7f9fa7a1403a1169e86430a2a782137093f5456e142aad03a5f7a66d38009dd01b7fc02c9cf61642dedaf7cc8d46066c281ee17780674c3a36eae66c58d2d765075
|
||||
CT: 9c44d9135db0dbf81c862c1f69bec55a279794cdd29a58e61909aa29ec4c120c9c5a508d856b9e56138095714a4bb58402a1ad06774cf4ecdf2273839c0007cb88b5444b25c76f6d2424281101d043fc6369ebb3b2ff63cdb0f11a6ea1b8a7dafc80cdaef2813fa661
|
||||
TAG: 65c746f659bcbdcd054e768c57c848c9
|
||||
|
||||
KEY: 0cf8c73a6cffc1b8b2f5d320da1d859d314374e4a9468db7fd42c8d270b7613a
|
||||
NONCE: 3c4c6f0281841aff
|
||||
IN: 4434728d234603c916e2faa06b25d83bad3348990ecde2344368d1a7af1309bd04251bb2e0b72044948f8dea33cce2618283b6af742073a9586b26c1089335fe735141e099785a1235810a3a67ff309e2f0ce68220ba0077ad1a5dc1a4aef898a3b9ff8f5ad7fe60149bd0bd6d83
|
||||
AD: a38d09a4f1c9241623c639b7688d8d35345ea5824080c9d74e4352919db63c74d318f19e1cbb9b14eebd7c74b0ad0119247651911f3551583e749ea50ff648858dcaaa789b7419d9e93a5bf6c8167188dbac2f36804380db325201982b8b06597efeb7684546b272642941591e92
|
||||
CT: bdfbfea261b1f4c134445321db9e6e40476e2dd2f4e4dbe86e31d6a116d25830762e065b07b11a3799aab93a94b4f98c31c0faeb77ec52c02048e9579257e67f5a6bae9bc65210c25b37fc16ee93bda88fd5f30a533e470b6188c6ce5739fa3e90f77120b490fc1027964f277f40
|
||||
TAG: 4993ee9582f58eabdb26b98c4d56a244
|
||||
|
||||
KEY: 69f4e5788d486a75adf9207df1bd262dd2fe3dd3a0236420390d16e2a3040466
|
||||
NONCE: 6255bf5c71bb27d1
|
||||
IN: c15048ca2941ef9600e767a5045aa98ac615225b805a9fbda3ac6301cd5a66aef611400fa3bc04838ead9924d382bef8251a47f1e487d2f3ca4bccd3476a6ca7f13e94fd639a259ef23cc2f8b8d248a471d30ac9219631c3e6985100dc45e0b59b8fc62046309165ddb6f092da3a4f067c8a44
|
||||
AD: 0c83039504c8464b49d63b7f944802f0d39c85e9f3745e250f10119fa2c960490f75ae4dced8503b156d072a69f20400e9494ab2fa58446c255d82ff0be4b7e43046580bc1cf34060c6f076c72ea455c3687381a3b908e152b10c95c7b94155b0b4b303b7764a8a27d1db0a885f1040d5dbcc3
|
||||
CT: f0bb2b73d94f2a7cef70fe77e054f206998eacf2b86c05c4fa3f40f2b8cebf034fe17bcbee4dea821f51c18c0aa85b160f8508bd1dc455cc7f49668b1fb25557cdae147bf2399e07fcacaca18eccded741e026ef25365a6b0f44a6b3dd975ee6bb580f5fccd040b73c18b0fbf8f63199ba10fe
|
||||
TAG: 4236a8750f0cafee3c4a06a577a85cb3
|
||||
|
||||
KEY: ad7b9409147a896648a2a2fe2128f79022a70d96dc482730cd85c70db492b638
|
||||
NONCE: a28a6dedf3f2b01a
|
||||
IN: 791d293ff0a3b8510b4d494b30f50b38a01638bf130e58c7601904f12cb8900871e8cf3d50abd4d34fda122c76dfee5b7f82cd6e8590647535c915ae08714e427da52f80aef09f40040036034ca52718ea68313c534e7a045cd51745ec52f2e1b59463db07de7ca401c6f6453841d247f370341b2dbc1212
|
||||
AD: 9a6defddb9b8d5c24a26dd8096f5b8c3af7a89e1f7d886f560fabbe64f14db838d6eb9d6879f4f0b769fe1f9eebf67fcd47b6f9ceb4840b2dba7587e98dc5cae186ef2a0f8601060e8058d9dda812d91387c583da701d2ba3347f285c5d44385a2b0bf07150cbc95e7fcfa8ae07132849a023c98817c03d2
|
||||
CT: c2f109d6d94f77a7289c8a2ab33bc6a98d976554721b0c726cbf4121069473e62ba36e7090e02414f3edc25c5d83ac80b49ad528cda1e3ad815b5a8c8ae9ad0753de725319df236983abd3f69ab4465d9b806c075b1896d40bdba72d73ba84c4a530896eb94ffccf5fb67eb59119e66a1861872218f928cf
|
||||
TAG: e48dc0153d5b0f7edb76fc97a0224987
|
||||
|
||||
KEY: 48470da98228c9b53f58747673504f74ca1737d7d4bb6dbf7c0cba6ca42f80b9
|
||||
NONCE: 56fb4923a97e9320
|
||||
IN: bc6626d651e2b237f22ee51608ddcffeba5f31c26df72f443f701f2b085d6f34f806e29673584cb21522179edb62a82427d946acabce065b88b2878e9eb87ed1004e55ef58f51ec46375ac542c5782725ff013136cb506fcf99496e13fcd224b8a74a971cc8ddb8b393ccc6ac910bd1906ea9f2ed8a5d066dc639c20cd
|
||||
AD: df8ab634d3dca14e2e091b15ecc78f91e229a1a13cba5edd6526d182525ec575aa45bc70fb6193ffcd59bad3c347159099c4f139c323c30a230753d070018786b2e59b758dd4a97d1a88e8f672092bef780b451fd66ba7431cbb5660ea7816cdf26e19a6ebb9aadc3088e6923f29f53f877a6758068f79a6f2a182b4bf
|
||||
CT: a62e313ecf258cc9087cbb94fcc12643eb722d255c3f98c39f130e10058a375f0809662442c7b18044feb1602d89be40facae8e89ca967015f0b7f8c2e4e4a3855dbb46a066e49abf9cef67e6036400c8ff46b241fc99ba1974ba3ba6ea20dc52ec6753f6fc7697adbccd02b0bbea1df8352629b03b43cc3d632576787
|
||||
TAG: 675287f8143b9b976e50a80f8531bd39
|
||||
|
||||
KEY: b62fb85c1decd0faf242ce662140ad1b82975e99a3fa01666cac2385ab91da54
|
||||
NONCE: 2f4a5ca096a4faf8
|
||||
IN: 03b14f13c0065e4a4421de62ab1d842bffb80f3da30bf47d115c09857f5bdd5756fd7c9ac3d9af1c9fb94f2640f7f4386cfba74db468e5288dbe4dd78bfe4f69e41480ca6138e8beacc6eaa3374157c713cfa900c07dd836eaecc8827fa3e70e052ae09e8473e2ae1a10b1bb669ef60a8dd957f6553daa8114918e17371f2ac327bd
|
||||
AD: cfe3b7ab7550b0e8e2e8235fa0dcef95647ce6814abd3dc3f5a3bd7d6d282504660c34ad8341e4d11402c7d46c83a494d7ddb105e1002979023e0e3dc2978c9ae53e10eb8567e7a02b60e51e945c7040d832ca900d132b4205a35034fed939a1b7965183c25654931a9b744401c4649c945710b0d9733b87451348b32ba81de30ea7
|
||||
CT: 8965db3d3ae4fb483208f147276e7d81b71a86e7202ffc9b1eaade009bc016838dc09ca4bcf30887b2f4243fbd652cd90ebed1ceef8151ff17ea70518d03b0f2a24960aa7de9b30fa65c2e2d57360061aae6d9376e984e9fcd5e5dd0911a4bc8deca832ffb76f252bd7da523076593ba6b174f7d9fb0377e066ecbb6638036241e86
|
||||
TAG: 3d0fc53e9058c2be32aa0850e0fab5a6
|
||||
|
||||
KEY: de9c657258774d4ebc09d109a0fc79d66493ae578797cac4eb8830a6a4b547e0
|
||||
NONCE: b5e35fe3398efa34
|
||||
IN: 4d68fb683aa4f4c7a16ba1114fc0b1b8d8898610fa2763e435ded8771b3651078bef73d4dfd14e76a34cd5eb9ef4db4ead4da9e83f4ce50fe059977b2d17d687c29335a04d87389d211f8215449749969f7652dc1935a0f9a94538dc81dc9a39af63446a6517609076987920547d0098a9c6766cf5e704883ea32feaea1889b1554b5eb0ce5ecc
|
||||
AD: 436ea5a5fee8293b93e4e8488116c94d3269c19f1d5050def23d280515457b931bbed64a542b317cc5023d648330a4b7adca14dd6f3783207b94f86ccaa0a0ac39b7db00ac87a99e3cd8a764ed9c75da8454479636ab2b29e770b166a5b75cacc425c919bf1ce9ac34afe6b4425c3d9fd2e48bc81e7d15516d60e592bfcc2ebefb660f0995f2b5
|
||||
CT: 97a97b8f0f5420845ae8d57567f9bba693d30e6db916fad0b971f553ad7d993f806f27ab8b458d8046062ced4778c004b4f958a4436141637c6039963308dea2f54008b7feab79650295ed41bf9e65e1a2d75ab1c7b2a70ebb9e9f38d07a9a672d3e95ea78afe9ac02f2566b48b0251aef6eeeca8bd15bd8d43b559426aa9d15d960ee35cb3edf
|
||||
TAG: e55dbb21851e8a5b365f86d02518331c
|
||||
|
||||
KEY: 6885bd333c336c7672db8ebdf24c1a1b605c5a4ae279f0f698162f47e6c73401
|
||||
NONCE: f0c4a213a6168aab
|
||||
IN: fa905a2bfa5b5bad767239fb070a7bc0b303d1503ecd2b429418cc8feba843e5444ed89022fdb379c3b155a0f9ceab2979000a0f60292a631771f2fde4ef065aa746426609082969530a9c70ad145308c30ba389ea122fd766081511a031ce3a0bd9f9f583c7000b333b79ac004fbde6ec3eb2d905977ff95dcff77858e3c424fe8932a6a12139e6ec8d5e98
|
||||
AD: 8ded368f919efb522bb6a9ad009e02ffbc6a16536e34d95cdb34f1153d7cb7b0f3c2b13dd05cedae27cfe68ec3aca8047e0930a29c9d0770c1b83c234dcb0385deae7ae85da73a5f8de3dfb28612a001f4e552c4f67ae0e2ec53853289b7017a58591fd6f70b0e954876bb2f7ec33001e298856a64bb16181017ba924648c09fc63c62eff262c80d614679bd
|
||||
CT: 0cb3d6c31e0f4029eca5524f951244df042fc637c4162511fea512a52d3f7581af097eb642e79e48666cb1086edbd38c4777c535a20945fabc23e7c9277e2b960aac46865f1026eb6da82759108b9baece5da930ccfc1052b1656b0eadaa120ed0c45ad04b24ae8cdb22ceab76c5f180b46a392ab45b1b99c612546e6b947f4d5c06ad5abee92ff96345ad43
|
||||
TAG: d3b541ac446c84626daf800c0172eec6
|
||||
|
||||
KEY: fbc978abb1240a6937ccc16735b8d6ed5411cdbc1897214165a174e16f4e699b
|
||||
NONCE: 7968379a8ce88117
|
||||
IN: 1a8196cd4a1389ec916ef8b7da5078a2afa8e9f1081223fa72f6524ac0a1a8019e44a09563a953615587429295052cc904b89f778ef446ed341430d7d8f747cf2db4308478524639f44457253ae5a4451c7efca8ae0b6c5c051aaa781e9c505489b381a6dcba87b157edc7f820a8fbaf2a52e484dc121f33d9d8b9ac59d4901d6ed8996ed4f62d9d4d82274c449cd74efa
|
||||
AD: 3913cd01299b8a4e507f067d887d7e9a6ded16dd9f9bb3115c5779aa14239fd33ee9f25756d45262dc3011069356425b5c81a4729594e17c9747119f81463e85625d5603d05e00f568b0c800bb181eb717be8d7a93166a504ce1bc817e15530c5bd2b3df1d4222245ea78a38bc10f66c5cf68d661503131f11af885c8a910b6dce70bc3a7448dfae00595beb707fe054d3
|
||||
CT: d152bcb4c24c3711b0fad28548dc4db605bbc89237cdbea7dbf956b8855d1161a0781f27bd56d798141e2ace339955efb98fe05d9b44cd011e645106bf47726183958cb6df34ce5766695f60bc70b6fe0fabb9afa009a8ef043dbf75f861881368fa07726625448fe608d578cdc48277f2dc53eaaf1bdc075269a42f9302a57cad387a82c6969608acacda20e1cac4596c
|
||||
TAG: 945dca73cf2f007ae243991c4fbe0479
|
||||
|
||||
KEY: 77d1a857fbadfe01aba7974eea2dfb3dc7bf41de73686aece403993e5016c714
|
||||
NONCE: fdd913a321c40eb0
|
||||
IN: db8915bfe651e2ecb3ce0b27d99a6bfa7a7c507cfcb2987293018636c365a459c6a138b4428be538413db15bda69e697cbb92b154b7f4d2cbb07965225aa6865d7dcd1ba2c17c484b00b1986fed63e889f25a4966dc3ed4273f1577768f665362d7d3e824484f0dded7f82b8be8797ad951719719365e45abbf76324bc7d657799d4d4f4bb1dba67d96ab1c88519a5bee704f7214814
|
||||
AD: 3cb2c06c20cb0832bbacebfc205d77393ca1816346ea2681de4d3ab1fadb774ad273e4713290454496f5281ebc65e04cfe84ed37cd0aedc4bbe3decbd8d79d04a4e434876650e0d64309e336bfb10e924066a64acb92260b2dbd96735d03af03909aa6a80a6e89fda81037257aec21fe9be7e91a64e88e0a58fa38ecba4c4c4cffb61958f3c486cbb0b1d0b0014a2d1d3df248eec1ca
|
||||
CT: acb825e6023b44b03b2efc265603e887954e8612b2ee134bdcb61501cfb9492952bf67be597c3a005b09af74d9e421a576d2c65e98104780feab838d8cb1bd135452ea39dc8907a4c1a6a9161805e4fa3e16989e6a418a7eea2582bf895da967028eab7c95d846a6de4b9980785814cf00484baa2f6de609912fff689bce6e854261ffe866bd8e63274605c7c5ad677bd7897ade543e
|
||||
TAG: 938478a41a3223a2199f9276d116210f
|
||||
|
||||
KEY: b7e9b90dc02b5cd6df5df7283ef293ed4dc07513d9e67331b606f4d42dec7d29
|
||||
NONCE: a6c191f6d1818f8e
|
||||
IN: 2ada0e3c7ca6db1f780ce8c79472af4e8e951ddc828e0d6e8a67df520638ff5f14a2f95a5e5931749ae2c4e9946ae4d5eb5de42fb5b77d2236e2e2bd817df51be40b1b8a6c21015a7c79fe06dba4a08b34013dfa02747b5f03930268404c455dc54a74d9c6e35485e10026da573cb41cd50b64cfafe4cfcdf3c9684ef877e45d84e22bd5e15fa6c8fd5be921366ff0dc6fe2df45f7252972c9b303
|
||||
AD: 0f4269ed5ef0bfff7be39946a4e86e8bf79f84b70cd0b14fecb7be3c071316ce86de3d99d6871e0ba5667d9d7bba7dcaba10cb2a36668b6c3e2fb6c102938b75008bb9c213ebf9b85b5e91a802df0d31d7f11d764b2289f6225212694ab6b7c0e3ff36e84245d9f4f43fc5f98e654dea7ba9bd918658879c5bb4a1642af0d83113e3cf935d3c0d5208318f66f654eb17d8c28a602543e77ad3e815
|
||||
CT: 22586fe7338e99cdaad9f85bd724ba4cfe6249b8a71399f9a3707b5c4323b8d96679568dfc8d230aefb453df596e13eb3e8a439249bd64bc93a58f95089a62b94f6562b821c83d91f56c55147381e9de4beb4ae81bd6fe7caef7e7e9a2078f2fba8f3e70d4910da9accc92b8e81a61b0fefbece4bd89443e66e8ddda8e47a66a62f17fd0e7d0a4852ce1a4d43d72a0b5e8914bbec698f060f2b092
|
||||
TAG: c082470297da8c5f682a169d28bc0239
|
||||
|
||||
KEY: 6b2cb2678d1102f2fbbd028794a79f14585c223d405e1ae904c0361e9b241e99
|
||||
NONCE: 7b3ae31f8f938251
|
||||
IN: b3cb745930e05f3ab8c926c0a343a6eb14809fd21b8390a6fcc58adb5579e5432021765b2d249a0ecf6ba678634c4f53f71495865f031ee97aa159f9ead3a3fcb823ee5238bdf12706a9c6137d236e2e7110ce650c321e41daf0afd62bab2a8fe55d7018de49a14efe6d83a15b2f256d595e998d25309f23633360f5745c50c4e5af8ccc9a8a2cb47064105a023e919c7795d2dc331d3f2afb8c42e5c0bcc26d
|
||||
AD: 1c32fd3df22b3e440e2a3c7a7624990194cb16a5f74af36f87fd6ca7d410ce9064316a2d091945deef7d9b35ceec8396069307caced2b80afd7d53ec479c35cedf2dfd4c95c3dd8400f71ad34028c6e4f8681d93d0774064ba38f3fb9b0c1dfa1f5f0c7d20676a5911d999fb6a1d41367a8e99d852bf3d3b7b3f4c233249ed1ca135389a674ff48232ded3f6800a97b6d409c40e6cd70d09bf9d2ad25d9b9485
|
||||
CT: ef70c7de98ab1d4ad817024a970be463443640eb0cd7ff234bdd00e653074a77a1d5749e698bd526dc709f82df06f4c0e64046b3dc5f3c7044aef53aebb807d32239d0652dd990362c44ec25bf5aeae641e27bf716e0c4a1c9fbd37bbf602bb0d0c35b0638be20dd5d5891d446137e842f92c0ee075c68225e4dbacb63cc6fb32442b4bcda5e62cb500a4df2741a4059034d2ccb71b0b8b0112bf1c4ca6eec74
|
||||
TAG: 393ae233848034248c191ac0e36b6123
|
||||
|
||||
KEY: 4dbc80a402c9fceaa755e1105dc49ef6489016776883e06fcf3aed93bf7f6af7
|
||||
NONCE: 2358ae0ce3fb8e9f
|
||||
IN: 197c06403eb896d2fa6465e4d64426d24cc7476aa1ae4127cd2bd8a48ce2c99c16b1cbf3064856e84073b6cf12e7406698ef3dd1240c026cbd1ab04ee603e1e6e735c9b7551fd0d355202b4f64b482dd4a7c7d82c4fe2eb494d0d5e17788982d704c1356c41a94655530deda23118cba281d0f717e149fbeb2c59b22d0c0574c1a2e640afad1a6ceb92e1bf1dde71752a1c991e9a5517fe98688a16b073dbf6884cfde61ac
|
||||
AD: cf6ce7b899fb700a90d2a5466d54d31358ecf0562e02b330a27ba0138006b342b7ed6349d73c4c5c6d29bde75a25089b11dac5b27adea7e7640ca1a7ceb050e3aae84a47e11640a6e485bd54ae9fdb547edc7313d24a0328429fcffd8b18f39880edd616447344ebeec9eadb2dcb1fa7e67179e7f913c194ebd8f5a58aea73b0c5d1133561245b6d9c5cfd8bb0c25b38ffb37db5e2de5cdded6b57355e9d215cb095b8731f
|
||||
CT: aa87f9a83048b6919c8f2b050315db4e2adae4a9c2ca0109b81961b520e63299dcb028cec0b9d3249a945ee67dd029b40f361245c740f004f8cf0d2214fcfa65e6124a3e74b78aa94345c46fdc158d34823ed249ee550431eaae9218367321cdd6e6a477650469bb3cc137a8f48d9cf27934b16703608b383d2145659922fb83bb2e7ee2ef938a90f2ff846a4a949129b1fb74dde55c5ae013c2f285de84f7dac7d1662f23
|
||||
TAG: 06b4318ac7f65d556f781428a0514ffe
|
||||
|
||||
KEY: 9e4a62016dae4b3223fed1d01d0787e31d30694f79e8142224fe4c4735248a83
|
||||
NONCE: 263a2fc06a2872e7
|
||||
IN: 5a46946601f93a0cee5993c69575e599cc24f51aafa2d7c28d816a5b9b4decda2e59c111075fb60a903d701ad2680bb14aeda14af2ae9c07a759d8388b30446f28b85f0a05cd150050bd2e715ff550ebbd24da3ebb1eac15aba23d448659de34be962ab3ab31cb1758db76c468b5bb8ce44b06c4e4db9bd2f0615b1e727f053f6b4ffb6358d248f022bcad6ca973044bed23d3920906a89a9a9c5d8024ec67d7f061f64529a955ce16b3
|
||||
AD: 4cd65f68f9f88c0516231f2a425c8f8a287de47d409d5ecde3ad151e906b3839fb01bb91a456f20ea9d394d4b06604ab1f9009ef29019af7968d965d1643161ab33a5354cda2fdc9f1d21ec9cb71c325c65964a14f9b26eb16560beb9792075a1597394000fd5f331bd8b7d20d88e5f89cf8d0b33e4e78e4904bb59c9c8d5d31ac86b893e4a0667af1be85fdb77f7ec3e2594a68048d20c2fb9422f5879078772ee26a1c560cbcbb2113
|
||||
CT: e944bb2ab06d138ad633c16ce82706ecf0ef5d119be1f3460c9ce101d9c4e04ef1677707fca40d1f8ca181e07273707b06624d6d7063c3b7b0bb0151b757b3e5237fb8004c161233d8bc7e5f28ea1c18da1874b3d54c5ad6ff0835eed35c8853704585cf83996e5e7cec68180af414e04f08134d3b0384ebdf0393c9310b55d8698fe10cb362defc0995e9a13b48b42cff61ffd9fe4c3c8c6dab355713b88f6e98a02e7231a0c6644ec4
|
||||
TAG: 27de0d4ca7648f6396d5419a7b1243b7
|
||||
|
||||
KEY: 18ca3ea3e8baeed1b341189297d33cef7f4e0a2fab40ec3b6bb67385d0969cfe
|
||||
NONCE: b6aef34c75818e7c
|
||||
IN: ef6d1bb4094782f602fcf41561cba4970679661c63befe35ff2ca7ad1a280bf6b1e7f153fa848edfeffe25153f540b71253e8baba9aeb719a02752cda60ea5938aab339eead5aabf81b19b0fc5c1ed556be6ad8970ea43c303d3046205b12c419dea71c4245cfedd0a31b0f4150b5a9fe80052790188529ab32f5e61d8ccde5973ed30bdf290cbfbd5f073c0c6a020eac0332fced17a9a08cef6f9217bd6bef68c1505d6eed40953e15508d87f08fc
|
||||
AD: f40f03beaa023db6311bad9b4d5d0d66a58d978e0bcbbf78acebde1f4eb9a284095628955a0b15afc454152f962ec3ea2b9a3b089b99658e68ede4dee5acd56672025eb7323bcbc6ba5d91c94310f18c918e3914bbbf869e1b8721476f9def31b9d32c471a54132481aa89f6c735ab193369496d8dbeb49b130d85fbff3f9cb7dccea4c1da7a2846eef5e6929d9009a9149e39c6c8ec150c9ab49a09c18c4749a0a9fcba77057cdea6efd4d142256c
|
||||
CT: c531633c0c98230dcf059c1081d1d69c96bab71c3143ae60f9fc2b9cd18762314496ab6e90bf6796252cb9f667a1f08da47fc2b0eecda813228cae00d4c0d71f5e01b6ce762fa636efffe55d0e89fdc89ba42521cc019ab9d408fcd79c14914e8bbf0ea44d8a1d35743ad628327e432fdcfeb0b6679ddca8c92b998473732abd55dba54eefff83c78488eee5f92b145a74b6866531476fc46279d4fde24d049c1ce2b42358ff3ab2ba3a8866e547af
|
||||
TAG: a0a5242759a6d9b1aa5baf9a4ef895a2
|
||||
|
||||
KEY: 95fdd2d3d4296069055b6b79e5d1387628254a7be647baafdf99dd8af354d817
|
||||
NONCE: cd7ed9e70f608613
|
||||
IN: 0248284acffa4b2c46636bdf8cc70028dd151a6d8e7a5a5bc2d39acc1020e736885031b252bfe9f96490921f41d1e174bf1ac03707bc2ae5088a1208a7c664583835e8bb93c787b96dea9fc4b884930c57799e7b7a6649c61340376d042b9f5faee8956c70a63cf1cff4fc2c7cb8535c10214e73cec6b79669d824f23ff8c8a2ca1c05974dd6189cfee484d0906df487b6bd85671ce2b23825052e44b84803e2839a96391abc25945cb867b527cdd9b373fbfb83
|
||||
AD: 24a45a3a0076a5bcfd5afe1c54f7b77496117d29f4c0909f1e6940b81dde3abacb71ec71f0f4db8a7e540bd4c2c60faee21dd3ce72963855be1b0ce54fb20ad82dbc45be20cd6c171e2bebb79e65e7d01567ad0eeb869883e4e814c93688607a12b3b732c1703b09566c308d29ce676a5c762a85700639b70d82aaef408cf98821a372c6a0614a73ba9918a7951ea8b2bb77cd9896d26988086d8586d72edc92af2042ff5e5f1429a22f61065e03cfcd7edc2a93
|
||||
CT: 40c6318d9e383e107cdd3e1c8951562193c3ef64ee442432a63e2edefc78f32ab07772aeac172cb67ecf4d21f8b448423527bbeb9d8ddd0b46bdb27f74096ceb24e41963b4cdca176676a75bdbe3abc270b349ac0c6cbd9c3a5cd5bce20202fc5cc0c1bdd4fd25e121e0a24bd7bbeb9b19b1912467bf5338ee2ce88aa383c082b42cc399c9654ca325f35523e81438beb3f8926be79c378822d7c8f785614408a5f7cac49e4543188725643e6c1a70b46d0ec400
|
||||
TAG: 5801e84192c7267f66b0e04607a39a3e
|
||||
|
||||
KEY: 6ae1102f84ed4dc114bb9d63f4dc78d7dbb1ab63f1659dd95f47940a7b7a811f
|
||||
NONCE: c965d578ba91d227
|
||||
IN: b82a8a9209618f1f5be9c2c32aba3dc45b4947007b14c851cd694456b303ad59a465662803006705673d6c3e29f1d3510dfc0405463c03414e0e07e359f1f1816c68b2434a19d3eee0464873e23c43f3ab60a3f606a0e5be81e3ab4aa27fb7707a57b949f00d6cd3a11ae4827d4889dd455a0b6d39e99012fd40db23fb50e79e11f8a6451669beb2fbd913effd49ad1b43926311f6e13a6e7a09cf4bebb1c0bf63ce59cd5a08e4b8d8dbf9d002e8a3d9e80c7995bb0b485280
|
||||
AD: dfd4ac3e80b2904623ff79ea8ee87862268939decf5306c07a175b6b9da0eb13ac209b4d164755929e03240a0fe26599f136fb2afdffd12bb20354aa1d20e5799839abb68ae46d50c8974e13e361d87ef550fe6d82e8b5b172cf5cd08482efdef793ede3530d24667faf3a1e96348867c2942641f4c036981b83f50236b8e8a10b83ebf6909aad0076302f1083f72de4cf4a1a3183fe6ec6bfe2e73e2af8e1e8c9d85079083fd179ccc2ee9ff002f213dbd7333053a46c5e43
|
||||
CT: a9aeb8f0a2b3ca141ac71a808dcc0c9798ac117c5d2bd09b3cfe622693a9f8ca62e841b58bddb2042f888e3099b53638b88dfc930b7a6ee4272d77e4b1d7e442bab6afbde96ab0b432f0092d9ca50eef42f63c60c09e7b8de019b32ebe4030c37b8183cc1e3b913b0ce4ee4d744398fa03f9af1c070bed8cdafd65b3a84140cb4deadc70184de757332ce3780af84353f540755227e886a8d7ad980f3dd6fd68263d82e93f883381dec888bc9f4f48349aa2b4c342cb9f48c6
|
||||
TAG: f26b3af8a45c416291ce66330733b2f8
|
||||
|
||||
KEY: 405bb7b94715b875df068655f00513cb1ae23ffaac977ce273e57d3f83b43663
|
||||
NONCE: 5c6da1259451119a
|
||||
IN: f9f143c0c52c94b4ba7b0608b144156a49e7b5d27c97315743d171911e3645ab7957c80924e3c6b9c22ab7a1cac4b7e9c0de84e49fd5e4a2d1ab51d764fc5670318688ec942f7ab34c331dce8f90fea6972e07f0dadec29d8eb3b7b6521ddd678a6527a962f4d8af78c077e27f7a0b2ef7eabd19e92b7f8c1e8fb166d4763ce9c40c888cf49aa9cdfc3e997c8fe1cce3fe802441bbd698de269ff316f31c196e62d12c6bb5cd93fb3c79ca6369f8c1ac9102daf818975ea7f513bb38576a
|
||||
AD: 6fe6446505677bf08b385e2f6d83ef70e1547712208d9cebc010cba8c16ea4ece058d73c72273eed650afdc9f954f35aa1bdf90f1118b1173368acbc8d38d93ebf85bd30d6dc6d1b90913790c3efa55f34d31531f70c958759b2ba6f956c6fcdd289b58cb4c26e9515bf550f0fd71ab8527f062c9505cbb16e8e037d34de1756bef02a133dbf4a9c00ac03befc3fb7f137af04e12595ce9560f98b612480fcdba3b8be01db56ebec40f9deae532c3b0370b5c23a2a6b02a4de69efa8900c
|
||||
CT: 1a4b073881922c6366680cc9c2a127b26f264148651b29abb0c388cf6c9b1865dba5a991e1f8309efbdb91bce44b278772c58fd41273526c33fec84beb53d1689b9da8483f71be6db73a73417069bb4cd3f195236e8d0a00d124eed3a6b6f89415b19a27fbe35774f6a1a6ee4bd4350b252b975f0db2d2eea82f4836350850d6290901e726e8af13644e2d98bc1d569c20800521e6affe976bd407049a2e6d9dd23f88d52e651391ecd2fc45b864310824aaadfa203762a77c1d64562dae
|
||||
TAG: 0060026d3efc120f11c0739959ae0066
|
||||
|
||||
KEY: 8c602bd94c630cd00c7a9c508067a5a9f133d12f06d9f6fe2a7b68dce4786d8a
|
||||
NONCE: 760de0f7b7cb67e2
|
||||
IN: c3ff559cf1d6ba6c0cc793ca09a0ba573a28359386a6ec93e1bacd8e630209e0b477a20aedec3c9cbf513ee6a1e3887112218d6155b9875f7e6c4bbba2c31972e905d19f529f4f0f9502996199f94f8728ba8d6424bb15f87fcacd88bb42c63fcc513759712bd0172b1e87c9da122f1993ffb7efd3a5c34b240dd3db89dddea36dbeb2836d9f8648f8e7cd428c0f948097af753b35f9876059e7702027bb00dc69071206e785f48fcbf81b39cc0343974ac70784a2e60c0df93b40379bea4ad8cac625
|
||||
AD: 9e14907c3a8e96c2636db1f3d78eb1f673d6ef043cbbb349467f1fe29bf60f23d5d5d1c3b133a8ad72065d822347541c13d1574baf737eb3cc3382fb479e6d5193b9c8e7d2444c66971ef099dc7f37f6cd97b9f7959d46e2cf25e8a5b3111b4d9e2ef906d905f0ee2d17587f7082d7c8e9a51509bde03d3d64338e1838d71700f1b4fcb100b5e0402969da462f26f974b4f9e766121f8fd54be99fc10beb9a606e13fbb1f960062815d19e67f80093360324013095719273c65542b0e31b1a2a3d928f
|
||||
CT: 2794e6e133f6892f23837fff60cf7c28ee9942f8982ef8089db117903d0143293fdf12ea1cc014bcd8806fb83c19570eed7af522db0de489bbc87133a13434518bcfb9cda4d9f6d832a69209657a447abf8afd816ae15f313c7ea95ec4bc694efc2386cdd8d915dc475e8fadf3421fbb0319a3c0b3b6dfa80ca3bb22c7aab07fe14a3fea5f0aee17ab1302338eeac010a04e505e20096a95f3347dc2b4510f62d6a4c1fae6b36939503a6ac22780a62d72f2fc3849d4ef21267fffdef23196d88fbb9b
|
||||
TAG: 457cce6e075ffdb180765ab2e105c707
|
||||
|
||||
KEY: bd68ff5eb296c71cfe6bc903c14907f7726bcb1331f0c75f7801cd1b7948f3a1
|
||||
NONCE: 65a748004b352ba6
|
||||
IN: 52bf78c00f6e5dca2fc60e2e9a52e827df97808e9cf727773860cafc89f4b64178a19b30b46ed813fe00c8f09b25a6a1b6e350d5b005122934a59bfbd5e6e0c635c84a5226c3f2f7dcf951560f18ac220453d583015fdb2e446c69c6e6fdecf2e595e04fab1b0c506e3c6bd5e4414a35f15021e97f447aa334f54a8f1ef942dec6273511b5668b696fca97188ff15ed84b2f46145cce031c1a7f00bd88bb83d90797edc46161b3fda7a2299173496d73b812139556e8b4eb318078b9eb2ae5046e83b79dd3d45950
|
||||
AD: 5557b08a5010cbc9f46bb140c2505f68684eb24889324bff44b27234fd7a95a99cfb4ff90a8f9982085b725f78ac42eca6ce7f3314e457dc41f404008681a9d29ba765660de2e05bb679d65b81f5e797d8417b94eb9aabbd0576b5c57f86eae25f6050a7918e4c8021a85b47f7a83b4c8446898441c5cc4e0229776ef3e809cb085d71f3c75ec03378730cb066150f07e60f96aec983c0e7e72bf6bf87ae42228dfda195f97855fcdf4e6d1c4479d978abcfa276d16ed60ecbfbfc664041335ce65a40a2ca3424df
|
||||
CT: a5c8cf42287d4760fca755e2111817b981c47e85b0047de270ec301ca5f7b3679f4749210892b6ea6568f3a6a4344734a0efc0120ffedecf212d55cbcbb67815ac964875af45f735b70092a8f8435f52fc01b981ae971d486026fb69a9c3927acfe1f2eab0340ae95f8dbee41b2548e400805ece191db5fd1f0804053f1dbfaf7f8d6fded3874cb92d99a2729d3faaa60522060cf0b8101b463b3eb35b380fcddb6406c027d73fe701a5090c8dd531c203ce979e26b9ced3431e2b726a7244a20d9377bd62951bf5
|
||||
TAG: 4579fa1fdb4c674cc3cd232b8da52a97
|
||||
|
||||
KEY: 934fd043c32d16a88fad01c3506469b077cb79d258b5664fa55ad8521afdcaa2
|
||||
NONCE: c7091f6afbbeb360
|
||||
IN: 2bdd1fc4f011ef97ea52ec643819941c7e0fb39023c2f3c7683804a0ddee14a5d1784a5246966d533b3538edc7d8742d27061c3cab88df0318ab242102de3a54d03632eeb871b72c7e8f8065b49f4a91e95e15f3f46b29fd76b8fcea0d23570c5530e3bbb8a6aafa9ae32c1b3eac653c5ed5fdb2da5a986075808f6385870c85b1913e26042a9d8e78f5bc2ea6de5a64f8aeafa22adcffc7f6932d543c29bb3a04614783f948680e433a71573568d2ce984d249fb4fc06a9f358c76aa3e64a357f4eae924c1356bd5baccf7e0f
|
||||
AD: f737dd85638eb324dd3891219c5eef7c2dd053cfd055d447a411eba304a4b27dce981d112c4540590933c153d603022c91ebd2b4a58069d27e6ca17a462ef822ca41bffa80b43a68b1b564644cb3c5a7f0fddf7a13a30ff24437fddd8ef93c6f6f205d054f81890d982bd4d4ece0b1563677e843fe48c1f54e9a57ed4da66061482712e710a401073be5080d5b8b96525bffa67de5af31d50385fbbf1a87c21bf0e0a1fdff69ec32c7b7103e0b8ee6c844245e0fc84b9f89fcce62966cea68e2871d3b82e8df424c76309fc88d
|
||||
CT: dd13fbf22c8d18354d774bcd18f7eb814e9b528e9e424abc4e3f2463195e8018576565d16ab48845d11c9277f2865ebb4dc412fd5b27078f8325eadf971e6944c66542e34d9dda971e2aba70dbd3e94a1e638d521477a027776b52acf90520ca229ebc760b73128879475d1cbe1f70fc598b549cd92d8a9ac6833e500c138c56474db84cb3d70b7aa4f293a4c2b4d818b0ff9fd85918dc590a12a8c0e375c4d98b7fc87596547eb960676aad5559834588f00f251a9d53f95c47af4df3c4299175d5211779c148cfc988a5e9d9
|
||||
TAG: 476616ea15190c1093fdc4a087643cae
|
||||
|
||||
KEY: f9f6eb9ad736a8f66e7459fef5ec2890188dc26baf34a95f6f0384e79f5c6559
|
||||
NONCE: 7858dfc084fe4b0f
|
||||
IN: a644ca6e7cc076e87eb2929fd257693fce0f6fb64fd632f7f07c648ebd03696c8e262e6a810d7b7c4e5eef8c65b5323c99dbba50a70b4a9e5c2a9e7315973cd67f35d8052ce9a85a206416dd3031929f4f929b13d0a5fb10cb73c65f6c0ace019da146b51c5274a099f44e3669d26add6f2ff081e886f3cf952fe0dbbe6b0534c23e307574bd35fbd657f5fcbd5dc19fb382a1dc0a2dc8285a0350f71554e4c601497749e35567dd4a273cddc9a48ce53a5f1d297fd8baf8d1b9feb35d9151114345abada4d90db947bb9a743c175f5653d1
|
||||
AD: 2048d1c2ddfb5ec385b201832c7a993f229ba72ec16d6ebf723ef0c5032b9966209a9e8a63151b40412e96b82f86728ea6588c7e8e11ac71cc8eabab8c4b54de866658d9c5011def61fb3dbe4e630158a45ea41a2ed55ebd1efb1abeda7637de6fa5fd2f151c6d2f385bf6cd002ca8b4a2896e0d65944ee913e3c784669dd201b1985ef3577f7f123a5f9bcffa176c8f557c4f729133cac518642f27d9b22ca9b97faaafe5b669a10b79ace4a7d5727df146c77ce681357d69f9c2d65b4401bd73cd113387e3b3a05d897adad7a24c485e7b
|
||||
CT: 4146faffd7313f5d9f625370d20413cc62ab65f4acfa3c7ee1125b937dd7a39f638fc46c8ed004fb525698de5d8620ec153435571817c3de257b0d0e648ebb92940c86a98262d54e764f28cbdd4f7d9bea970291f2110414f62064d7229c6332236c507b3dac742e651d85a2a22fb243c0cc7cc2d016e5bea38f33f9a9ce048944a5fe8b078d71d23168e12dfe5a0f0b829771edc7073fb96032b7be471337a37aca0cf7c0cdd543eed686cd34934717fd79a3f18492eef72f9f450b880aa7e2e1b65e3b04c22e72301338b43aa32ceec2e6
|
||||
TAG: 10ffaf2be316676da02d7473a9df87b9
|
||||
|
||||
KEY: 29b19636cdd32507fd98ec4ee26caab1a917646fb8f05b0dc01728a9f4a127f0
|
||||
NONCE: 06699d245916686d
|
||||
IN: 5fdf913aceab1d6dbaf7d9a29352fa8a3eb22718043a79cffa2fe8c35c820aec7c07644b8785dcf7a433b4189abb257fb12b06fae0662641011a069873c3e3c5ccc78e7358184a62c2005c44b8a92254958eb5ff460d73cd80284d6daba22c3faba046c5426fe8b7cacec64b235a8f8d3e2641e5bc378830594bcfb27c177aea745951ee5780a63705727ef42c4ad3abf556d88e3830f3db6b09e93edd09485cbf907f79de61f8dc5cb5fb7665ffa0ef53cb48702f6a81d8ad421cef20c1dbdf402b8fafed56a5361b2f93f914a2380fdd0557faf1f4de
|
||||
AD: 39116c49cc13adb065b92cb7635f73d5f6bf6b5ccbf72a3f65a5df6bd4a661105015358d9e69f42e98aed795e8161282bc113058b7ef3b9e23fcd8eeab34a392e03f4d6329c112cb968385ec52a7afc98bb8695785af6b27b700973cc952630b7247ce226b4fbb99b8a486370bf6345d4516c52c64e33f407c4f2d1ba90545c88732d98bbd97972ac5e94c694624a9b3782b0099824651cb7567914d25b3e13181a791dbcd40e76e836b3350d310a52151bf835d3c357c9871482c2928e8404c6e533406d4d6fa8f63366f2c4ed828141f1ff00f01a536
|
||||
CT: 01e237220b619054a1f3670928fe67d40484b5af40fbd04d032500aac5acaa3b4584dd99a58c390627636a50de5d744f76a56a33205f9e3b00e16162eb47ff3333e1e208ca200f1a5338a86e17bd92dd2d16af8bb022a7dc05b923d019e05247f1a0d0b4bfcfce58dd6d83830705707676d55739abee89fcd5cb94b8fde006a5da02df64b00a467f45970b5ca440f22319b9735a55d454b9fba0588fef0c59d3d83823eba6e0601a96e10233826c5adeea6b2a51d386a07a9e047ad405b23d4c3d89f30c31e3199f0c8f927bfac43ceea1f969de0a8c0f
|
||||
TAG: 092f9f3c5d4f2570c9946c87967f4579
|
||||
|
||||
KEY: bae06b9b5456707551c7b0e207aae02a19b4848ad8ca4ce40705bf8c856a6e52
|
||||
NONCE: 9c27065c3ef2d522
|
||||
IN: 50cdd88137ff428a88e87b5845be4924f6387537bb5c0b654c80107ab5698db75b2e131848e7aec156d31aed0766d31c379fece4095d38264c6d5945974d25f729c3b0ba11ea853e9cebdb6f03bb670fce08adff74d0a8f02d633fb34e0fb7337a8e66e1c12084d914fb6173b8105684db822752c6751a372bb16690284d661b8b8bc6a6dfbddf45ebc2219596f9f2f878c118df69030de38b4d99dde43b9b9e20a3dab691645dd518342f49b06a0fe0a397adf261e99f07af5b0b3798b1022ba0939c42a54d3b93641cffa3c2e174bce9ab7ad7e7c7924308d1a77a
|
||||
AD: 5d5590db1bd316eb7a0e30e4c7a6dfdbef9d3287fdb8d824389599c3c2ee262b2192eb5b9708e66e22dbc7eca83fa1a995da3ce64c86fe5aa08b826d476dc439497e2d12e2702c63c8d27aa7f09fedee816dc8bffe1351d53271a34d4292b613b7efcedb7e3cf3e6ad389eef12471e9e20e38e7ae22a323abbadfe8f2e84271bffb1819feb4f77b82843cb8757cfae293631bc6d39669107e7015c85d7343ffa6fc1bbe6f5ab4de30cd752a281e03061ea89de2a3f5e90e20da22fd6e8525c100738667f42212b2cf45fcb23bbb54b21c117484b22c6e514685314df
|
||||
CT: 66b7f69ac49fab4e5975aeb6fa9287d8eac02ac312c4de78f77f59da16cbcf87274e66801c4b862c33ea79cdc76528862bb2956c06db8b8acfac4794ebf39e35ac03cc73a4351a4ff762f681a48d6f25cad36e2814c9b5c40b9ae92509e58429106847789454d376836936bebc7a80e6c66e7aa52936d6b361378a41f849ad4e48f9ee2d3e92217a908fa8eb35736ac8ada7d32ae05391f2d807be3512543c36138a5fe660dd4cd4cd184bb43b6ba6bc0bae634e2fa9669304cd510ed5103f630068ff76d3375738de60a381842b421477e25a490cdd6894b2704125
|
||||
TAG: c9998a677dfb0e91924aec9de0afd585
|
||||
|
||||
KEY: 2cb374cb048c168f2e43597f028d9e73cade1b458284ffc260d4fc6b9011c414
|
||||
NONCE: 9fb909169bc9f4e9
|
||||
IN: 39eb929482784b463546f5d84f80510f2019923d465b99d194246d68c7ae343f91971d8f7059cebb86aa5dd099289aa648248b8c5ca04e66ac5e9bf06776e3883495397618a0227f035666806e636836b47d3d2d255a49db79866cf00d9ddabda259c4f968a1e01e651c7811cebbee2ee71803ea1d9d23487eb221f2d9555756800aba5e6abbefd6fb72b3151cc99ced599cd86df2a9b1ce94f89f347eeb124d9e7f0d9cc48d3dedd819e6d3dbac57ecee199547b266116a2035c9acc4c8ca3271ac74952372897c4a5f2cb84e2d81817fec9d6774f6d8a5b2021684132db4fca3
|
||||
AD: 0c7bd4f3a30ee944ccf9489181e6911684dcffad4593a9b65a67dfc80718c69b35897d01281016b7731e12c15cad8482e79458e08a755622e3f3f22a23ef6c8487a36ad1771ba06c641f06f85de0db3776cc6df06ad8fe3b4d60d58508de943083f17cbb9dc0d390ac94d8429e8c6fcfe063f424fbde0f62f6a7f91a626d195dc498a6e69bd93109c4e9ba13e7330aba456d710a4b0cc279d4045660406e26d61dff70d4a33c4f1052869f9248024e7a0f85f1effb32f6f7ccb1f860f3ef04e8f7b29096e6bcf9d4b3e0ce703e9bf228fdf515c2ff9cbabd16987be0f9babd3d8a
|
||||
CT: 91ddadb86b7ebef798ddaa59da51d71316fcf6c9678143178227d778750dc9827fc6cc21e605c505023e6db25849df7fb6fc1ca4d223aa215f8c85b724643c83bf8218815a9f9e2952384e0ca6a80a3760b39daf91a3c6154c4728c2371fd181fa3764753d0b0c23808a82cd8f0497246e3a0f17f8906a07c725d2891ce968a9d432c2b102d85c05510b28e715bb60d0403a77490e7f18be81218bc4f39287b9bb09f50227dd2f55e4fb70c4438da8ba3c8ffbced87d90155913faa9979fc57e6cbeddfaba3d3ab4163c0eebc7d94279c27d3ed56338893dba542eaefba30f8c3b
|
||||
TAG: 728e60f8124effbac234f70da925881c
|
||||
|
||||
KEY: f0f16b6f12b3840bbd1c4a6a0811eef237f1521b45de9986daec9f28fca6485c
|
||||
NONCE: 7ac93e754e290323
|
||||
IN: 0530556424d823f90a7f1c524c4baa706aad2807e289e9479301e3e7a71f2a5e14e6232ea785f339c669af2e6d25f1d5a261096a548d23864945c3a589b67b09b0304a784d61b42b2419139485242e0d51fcbe9e8fed996d214de8717e6a71f8987ccad65eb92e66707034a5ae38e6486e26eb4374c565aad5df949dab209f7f7bcd8eb6fc52761a26cfe5d01fd349e59f4042e6dbe6b232f9301b971dee121d8aa1e62d40f043a42f3aa859d867eb809b1ced5ae1ec62cacf94a69fafd0631a8b5dfd66d855900fb295eec90ae5fcbf77beae267a79d24081bb322d8c4e0630fed252541b36
|
||||
AD: 13bfcc17b810099cda31ca53a1323db9b07633ceb2088a42263a4cbd6a4d47978776005c9a20203319c3a3ae434e9a26fb541047dc9df38dc36c095267272e203d0b24d119a70a7e96041b6d82b7c4d5570e1e4a1cf2f6e44ae63fe005a1f5b900778c482f7bd89e2e02305e35b8f61b7bb2c78a13aebfce0145d1c5aa0bf1d10d23616d5a3a446de550302f56f81dc56fe4f3700f14242688d9b92d8a427979b403c8de8c493a2cde510eaf6b285e6675b173aa0314a386b635c7577d5aff0d868a0cb3f73c8d2005f8c7c9dab5a060ef80102c9d4a4af988838afe87aff04c0689e8c3c7f9
|
||||
CT: 2c14c3931e98e84507c4c165c2ed47ad4a178f0e216cd7ac2453bbbf9f85dd06bd8ef54a9ff1fd3dd8e0cafb635d8f2de861a0db5b14d03f17aaea8c89b3010797c71c13a0e666899d7ff6e53c4f08be8ddb3e37688b5afa088079b6c7519b833e16560073e699530302028a3496e05edddec01a23a4c7983956250e8d9e616f7b940856955cde81c1efabf6b7b92f153d03f4cd17e7f7d2907670cfc84d45c1d7936775a3fce47968504278ffaecacea0871b227f250e2979516f6fa310fec0d8df1af7872e5a534e82870aa05f43ef0a455846b93ce938064fa33e92de262e4156dae56775
|
||||
TAG: d95d73bf9aeb71eba9042396f3725424
|
||||
|
||||
KEY: 3792943c0396f1840496917ce8ad89608385007e796febeea3805f3f4cbeccf7
|
||||
NONCE: 23b2f9068b2c4c85
|
||||
IN: be6b67eb943ee7b5c785cd882f653e73a8f75b4a41a2a7c56ae5a10f729caf39948fe48ad0e51240e2e7aa43193c7ec6ce7f4909fc94c9f99e38e6a0ad7e98eb29c5c2e61c99e9cbe890f154185cec213a74725d23c1a4e4d0cb9b1a36b78c87e5eee20d2aa29aae80d4759eb0c51c5dc3a95bdbbf7e14eb434419a6c88a954ac03d0c98739f4211b8732acd71c297f578b8cb64ccac45f7235ddc7f2a3f5f997525c1ed39dc550126cdf9cedaf55425489085e91b170be6205a5a395f2dd4084a3e8dbc4fd8b13252f7effae067b571cb94a1e54aba45b1b9841308db0cc75b03cfce4ddafe89ce20f2d1
|
||||
AD: 7eb6d7b7bbaaa3c202a4f0f1de2263767169eb4a64853240d48c0f8d5d31b08d5baf42977614a57aad99426cde76d242cb37d2956d8c77dc4fd62a3abf30e8ac6cd58c8ef35e67497022960138c57787818892460f3bfc16e37ff388b1edc6ce2bc53c22717edc7a03d4c78b0dbbe9121c7fd8a3e3993b87a4fe389bff13bdae3b349de0b6db561602c53f746022aeb4483c723b67825042f4af20b7dd1e6031cf54215266295c524ac8e1370424c5c5e607fb3e23e97c8eebe64656775edf616422a8b974e1acf13ab45c9a367a7dd9b2d62f48bbc05819b65eccb813ca813f57b22ee4c280dbb5a9d8d5
|
||||
CT: 0b316ab2bcf5359900fa4082d5d253b49ad94b70e3fab544f98bd111cbcef6766cf953deec08cae1f489fe12f7acc0032db8a6b0c0eee0c206ea5fb973feaebf90f690e840094db5e13fdd7157ba127368c995b426529435a1bcdd1f14ce9125b8a0e4c96b6ec09e3c36a180adf81941c002d19c19d53c2009be803b987504606b7d43bdee5e0b32ff23c466b6cccfcd0d4e88fd1332e73712b5ab725c1a383e584f34f80daff29d285ae5e43cf1d0cc7a828e75c25daced3a581a93d7a50f313b33f38dddfaa23cd5b9914797db820ee2400d52bf5fa982277fe9b5881ac42981633b3957b0e935051828
|
||||
TAG: 01973ee2e81cef22751a6a8831d752ef
|
||||
|
||||
KEY: fe4be6054773f634356ac328591fbc6f833b0d1beeb38dd5b6feb7481b4489d4
|
||||
NONCE: 0b3f16f898a5a7d5
|
||||
IN: 76ced1ade6d1ef4069afddb32e7432d4ff2fd06685121f7b16464e7a72d365744f547d2ccf53486310e38b42d8bacaf711e54c5458d2d68c4dbcc8de31ab6732f4430e88a64565f5b287640775aaa2af1cc461d3e415bb275c6246b1b58517aa72667eae291a2982eda175d1b22c5a58e6fec2b3743d55712f201ca24ba5c0ae8c25724871b2ec2fb914a8da5a52670ab9b43a83b8568ce74db5c634061cb80530c8070c38b8f48c33ba136cb9f2158ee7eda8b65f2192fc94d1291f182f101795b7190c74b319d2d3e02a97c824d9c9471a83797e4936310b207e3a1e0bcf75f7c3e3ee48a747641cdc4377f2d55082
|
||||
AD: 834cd775cbefe4b33a3ca53a00c06a3c4a666983e4115a029f15729460daa45d1505e95172d3695625a186b28b8be173a925af04665f209267b3c5123e8be13da447ee1ae856bb0925f35aaa76e04a7bca8460f76c2024de2149f38a8cfba81694b854885d72568105571b6b213a0bc188a44cc7fe13153cbf261401b238cf12a95e23cb56f240114f16e2f1e3a514615aab4449c0c49e4d900b0e17d1a8dabb53d43dca32fa052d576b73dd9b40856b515d6d7efc2a5c17e0ebcb17bd59dc86f22ce909301a2652f134e82ef0e4519487ed12d51536024f2ae8f75d937c42d003076e5dea8de0c684cda1f34253d8fc
|
||||
CT: f8defb6fe95dfec499b909996a1f75a198a90e4d6c6464d00a357a555311c42fe92dbbc4b79c935e4f0b1a95e44fdbc1380bebabca28db4dd0d2870daaafc38ef27908c3509e945714801cc51f1a07b2430c74fa64f2a7c2f7fd1551d258c9c3be020873fc1bf19f33ab6c660911dcf2317195d0efee82d20ec26d22611f9cf86c51a64e28b3a1f344500018e0855c88dae3c07acaeaa10b60388484dce93e16e6e1a6e69e899806648a92568c8780e9f4baacd98cbb353ac2f908e775d92303cfab843f15be0e0c322a958802fb1a60fcc7631f151f4c2b8cb965d2d296acef250275a2fecc0cea803ce7c058b12dd2
|
||||
TAG: ade515091930dd7861b27f78a87ef60c
|
||||
|
||||
KEY: a288b11ce5382ec724ce4ab2d7efa8e777e91ebd04367935e15f9dac483e9596
|
||||
NONCE: 874144dbf648b325
|
||||
IN: 4c9195280a79a509919af4947e9e07231695fd7c5088539f23936ce88770ce07d9ad3ae4a463b3a57d0634d3a77ceaadf347a334682b04be8e58b8e86fb94a1f93255132b8cdb0df86f5bea354eea4e8315fea83e3fdf6e58aa9f26e93caa08e5e2551a94bd916a51fed29ec16f66800cda6a0aa24ec308bf5fb885afba272685de27c1edcdd3668048ef07b06e90d464a8aa28664903cac45e154e8e1e39c257e1ff506b9d95cef4f300bb73b899e7828602c3c1d290b8cf55ee5fd72ecce9e6efc9293aebf674a70e2a7673e75629c12950622dff71d3ec0992e57776c788c6927d30b4e24b749191c3ce8017f0ada6276e43720
|
||||
AD: 04abe8588c8c8c39a182092e5e7840442bd1c1149da102c4ee412bd8b82baa5087ef7291b5cd077c177c42770b0023e0e462b06e7553f191bcb0315a34918dcdbffe2b99c3e011b4220cc1775debcc0db55fa60df9b52234f3d3fa9606508badc26f30b47cdb4f1c0f4708d417b6853e66c2f1f67f6200daf760ceb64ffc43db27f057ad3ee973e31d7e5d5deb050315c1c687980c0c148ee1a492d47acfcd6132334176c11258c89b19ba02e6acc55d852f87b6a2169ed34a6147caa60906ac8c0813c0f05522af7b7f0faddb4bc297405e28ecf5a0f6aac6258422d29cfe250d61402840f3c27d0ce39b3e2d5f1e520541d2965e
|
||||
CT: 0afce770a12f15d67ac104ba0640aab95922390607473cbda71321156a5559906be933fb0980da56f27e89796eaa1054f5aacf1668d9f273cc69071b9e8e22af6a205a6a88f7ad918e22f616bddbb07c78913c7e056e769e6fcf91c7600c2740212e3a176e4110cac9e361a59a773457064d2dc652dd115d04f1c3756c0e1d39f6737a16b4508663e310934c49c58058b3c7b9af7bb2334c8a163608c42499658986927cda365e2aead3ac29de16e47e954383ea566f8fb245a4e5a934c767bb3bf7e0eb8a477fd0e1f61bcb238462a0d19c5cea9293ca58ade76829413216a7882cd2846323046694f78cd8b0347792ebb75abdc1
|
||||
TAG: 973e58b1b8adb176a6f1e5c963bfdc5c
|
||||
|
||||
KEY: 65b63ed53750c88c508c44881ae59e6fff69c66288f3c14cfec503391262cafc
|
||||
NONCE: 7f5e560a1de434ba
|
||||
IN: 845ef27b6615fb699d37971db6b597930a7ef1e6f90054791eb04ddfe7252b5f88fd60eba5af469bc09661c0987a496fa540621afeec51bebda786826800943d977039dee76235248112ff8b743f25ed5f3cb0d3307f5e118d84fdbb9c3f5531bc177fb84549c994ea4496c65e5249da987dd755d46dc1788f582410266a10f291c1474f732183a2a39afe603771bb9c423fe3e8906f2be44a0c9a7c3f0ceb09d1d0f92d942383a875c0567c7869f045e56dd1a4d6e90c58d44fe0c5760bb4fd01de55439db52b56831e5a26a47de14249453a4f8e7da3cb3282c6622916197ebfaad85dd65c61e7d2d3ba626276366746f396394c1bf75f51ce
|
||||
AD: 51a3588398808e1d6a98505c6e5601ae2a2766f1f28f8f69d1ccbcad18038c157b41525be58ae4527a073748b7a04809e52a5df0c7988417607738e63d7ead47db795a346b04e740186e73ccad79f725b58ee22dc6e30d1f0a218eda1791e2229b253d4ab2b963a43e12318c8b0785c20fca3abcf220c08745d9f9602f0ece544a05736d76b12d249699c9e3e99f3f13cf4e5dc13a04125c949a5b30d034b23cb364c8781964bc6c30e5e5ca9673d517ef5f35965d8a8cf1be017e343df97b6bee37b30638b154286d1f36d2f9a0eaa23cc484eac5a05b15d9efc537d989dbc8b3106c0dc1a56e97e6aec2eff54a82cf7ae9df2af46b4c860f83
|
||||
CT: 027b14197b4012256b133b78ddc94e72fb4d724fefa4ae329f5a5fa3fa784fe6d7e1e805e3f7a75557de64de506d38237b467fa577efb59e7cfe2356bed6655c5aa4e238dcfeb75c16549a0917268768a96acb5e20546a1fb7e3a7cff887f49f2cd7a135f72a98a779150f3207bf733e88861fd79eadbf77fa3bfe97bfe8b6a991cb3bcc2cde8287f7e89384846561934b0f3e05e0646e0e1907770df67a7594161a4d0763faa6fa844080932159999d528ee0558710058ce16f97d13ac9fd9bf5044191188bbfb598d0fafbdf790b61ce0781ecc04218a30ded45efd498cc9ba03562ed2b4a993ee98876b3ab7a9bc07829f1c4ca6ead98c06b
|
||||
TAG: e4d18a701b8308697b5e79141ed783c1
|
||||
|
||||
KEY: 4986fd62d6cb86b2eaf219174bec681bebcdef86c8be291f27d3e5dc69e2feba
|
||||
NONCE: d08d486620ed2e84
|
||||
IN: 3a22ad5de387db4fdd5d62a1b728c23a8dddc50b1e89f54f6198b90499f9da3122ebeb38ebf5fdfe30309734f79aff01e3de1e196b35bffa33bae451f31f74b8aec03763f9e0861a34fe5db0b40c76e57c7fc582bfa19c94ee25b5e168270f379bf9f8a0a18bed05de256f8f0dd7c23ba2ff1c7f721409462f04cc611ad9bd4c3c9acf30742acfb9518a6375cbb15d65a1bc6993ea434894f93d4f6e05996ebc1bd56579296309a2c6b8fde95072168b5fd31927c4c0abaa056bcd16221d5f220be47591f43255013a262dce439817f534830ba82155347e5fe3101f8011b89365a6568214ed0661914e8cb3431d6c8f2347dfc1209a3eca4aaf0a111f47fe
|
||||
AD: 7dd3f656a03c001b45ca0680bc3ac9d68c6e96b591d3c69eb8c65e489009d845cb331c98b82e627e06d5bf01e74c573df268c2386f12628c019951d42f55991ff20d72a7b2c45f41d0be7af428c92f324aaab8df70d900301cdf09a3d93eb711c919d34a86fff9cb078322ee2e0ad48dbdf3b7884f0f2dc5c36262c59bcfd75ac6200f59c6fcd0ce10ff5005fef5df8f0432377dfbfc1db8f559e27e1aeef3380ea3864867d36a25a18654779a751586cad3b8a46b90864ee697b08605673b8d2123433c020a21c4db243dde2420c12fd4d54a2704a0c8c376454a1b5e80fd6db89aabd56d9b421f29649e474824dfa56cb5c673c504d10be52b53751709fe
|
||||
CT: c40180afd53001663ff4834110f56e6b0f178cd3c0e7f7de5d0089ee41d8403ffb98e84922706544a344d7e2625b12cf66b9c966f9f57d7b94e3e4b34e6f0aaed1763ce012782e2f5e1682e6c343fc7961fedddd0919d0b910e9923c17e36406979b256b85aec24ee352f03b48c1302eab419c83dccc5372cc059e9de596224fa70098eb32fc9579e97917b923914fa2efc30ab29b457bf14e45583b3771486bdc0876f3ea6e1a646746c4f8c5cb2641a1557c8473e6ea67d4811a67485ae9a678ff3a2408ca845c3b51957e189eef47dfc1d46bde4b9d754d7df13f828ddadb06e4ebddb5f0dafbdb28de4c5e6078926f20cdf9e97ecd58e309e640f74f06
|
||||
TAG: fd5e29332832a14a31a9ce2ca8568498
|
||||
|
||||
KEY: 7d28a60810e43d3dfa32e97c07957ec069fc80cc6a50061830aa29b3aa777dfc
|
||||
NONCE: 47738ac8f10f2c3a
|
||||
IN: b50278ae0f0fa2f918bb9a5ed3a0797c328e452974d33cbf26a1e213aa20c03d0d89490869754abf84dbbe231d7bccdced77d53fd4527356d8e02b681fc89a535ae87308bf7fbc26197a5ea85bdb3aa033b8da5cd197ea6d72f96f63b03f4ecc7adedf399a5043776cdb32c08f30b77f34df85f8adb8e02649a04b020b03e17d445ca63e4ed73ae432c481392e031eba2f9d2f7f981d1e50917822bd6ff71c239d33444ada3523a59dfbce5457eadec1ab926c9e6c5299c7521e3f204b96901a712504fcc782e8cea80ba12a7f7e71cec3d0871899b6ca059061da037715f7d13fed01c9cade1e687b4fbb1f4ac4b040db3b43800f112fb900e4f772d61b921cbce4da6f
|
||||
AD: 324292813b7df15bc070cc5d8a4bf74ead036430be63abc43304cf653959a24a91c7de5a671c50fa8a87e21bb82b069999aadfb6895d8bda4c3083d17b8ca55b9ab1511ed8c4b39d8c28c11a22ef90c08a983e3fe2d988df9e02b16a20b24f39ddb28429625f511db08298c4dc321f6c268fc836a6191df6232f51c463a397a8d8b33374abe94e62c0f5c322387e1fc4a1c1980a04a1a3c2c31b32f183a11c3268c6dca521149dc16af120a78be6627210e8ddbc44472bc24d66ce3681c7579b3d9a425212a704a4f5105cb80f0d18ee860953d10b59c114826779bbc368d7a0eece9f223e47cd8e5fd453607d101d9d9c2bd9a658d6520b87d7b4263f6d845a524a36e4
|
||||
CT: 2c217e969c04740a1acfa30117eb5b32dc573df3354f4cc3bf8f696ff905f1e640f3b2c250473b376622e0c9bda13b94640521be1ef0fc660b4c10dbe2bfc093030753e04f6aaecf813b43b61f960455974b8bb8a9b461d1e8fd3802315e863c00448f24dd38deb90e135493274eb14ccbde15c50dcad734ed815a806be6622492a84cd062e3ba567b909a205a1d0d2bedd40169697d261c7b6c2e0b1f069853fd470e8f364a142c386c439a6dbe192ded5a3d0fbf73799f588c59e58c60249d980ddcf0d9693631cd9b3f972509c3a77123d38d9e267ecad06e1208e3f1c0a69fbca7c3bb1a48fda19493d0f8f48398820057b94120f3ef97d87e9e8a1b301a2534c68f
|
||||
TAG: 1fdd2dcd935f55822bf7231a516ca841
|
||||
|
||||
KEY: a76e9b916f5a67b78a5949651c8c3a9741a1bc3c41cdf85fd2c8f3e9a0616098
|
||||
NONCE: 0808da8292dc14e0
|
||||
IN: 9c149eeb09345c3c22462b03e49eb4dba6bc98b269b1086d752bcd8eea53b8977b238a04a994baf915591686baab90b79a3bf7d9adb2c6c2e31acd3e72f0813fb745aa5fb2e3da408f78001c9c09bd26a1a2646011b6120aaa2bbacc4a16c39fb5257b9b2ea2ad8bf70bcc9855cf11841116c2767310cf3cd49d1aa44cd505f079761e064d5bc7cea4a7173b086882a77d3fc179efc86fc4db8a373491d2ed81eabc63c950e832db17d09f474d4ec46bde47830caf26fabaa0372b81fccc449c0e19ccd630caf693a7b43bb1c408a54e03f50c44280a05ad89fb6e8f01d8ac278edf556e5d86ceb4b614fb2ef133819c6e1ff6abb86c54a135256204b5cd400b93624d3932e7c2b046
|
||||
AD: 6aeb7031e4a2e23eea93f05fdc562aa2bf43b8998bea7344377aaddc60fbdb7bcb1491d379ed0cb613ee757cfb66490db61bb431d2fad34b38ddd55bc5b22aa6c4773b9992f34b878c5663f6e8cdb5f80a17f4d312bf342492e48d1ce4c6d754076a634fece61500acf8168d47381af4faf980c6cac2bfd5da8c09b6edb0f543bf0fe02643e38d73fa37d8ae87fb66193f22e57faf4393c007d48c8631a685d520578f8f89db684fb371ea02f3a58b1e2168f0216321139472e0d03b6d90ba8aab65402e1c1ac4f9172a60e27e3d997b9b05e2f672120d6c87bcafa6d4c9b4cf8ba8a82932d92840368fc53dc5b48526103dcab5f1531038aabe89171327ac559b98a3cf4ea70bf051
|
||||
CT: 9c3faab9261a63cea9477b3269007283995b06ba77ef83d9e693f7e4ee9855550eef94855be39a7a435b6a3584b202973777c7b2482376ba47b49311947a64983b60236756ee4455d4cfada8c36af8eb06b06ba2f6b79ffb1185c89f2b2a831cfaa3855fc1841d8910908be5078352011168a67d36372d851a3217cabf593ea462dcd325cf9a4f67e85418fd5c924e9b92ab026cbee4e7ab1067066cb5949dfc699a68fe539e1abb13cec33904e5207e6963d24f5a0b770613b8b00014e791bfff88f9c25ca126127a2f8d1d1e9794efd28dce98b53e228073faae8d5047530d502184fc341321c3f55fcbf41187fc31262c325b97f519959b6a29b36c71f76f60196bb1457b77c8bb
|
||||
TAG: b45df119043d29008fcef36a169ef886
|
||||
|
||||
KEY: 98cd2477a7a072c69f375b88d09ed9d7b9c3df3f87e36ce621726f76e3b41a1d
|
||||
NONCE: 77d185aaf715aa48
|
||||
IN: 42b31eefdacab0f03ef6060156000c8195adb0976cabbe1a42bfcc09f85659c60b98638401f2d2e2facfb9a97a62926bb0cecaf3af0180a01bfb6e576babf7fc43331937a92abd30cddfa3e450f895e9dd914dea3fafd759c136d685310ebce28ac0613ccdbf30115946c9634b67510b77d0e37f07714b2ddac9d7095b8d4bd887c132c4a9127eb01c8dedb4c39c87b98a741316656f9a8d5a5b0c0ac84789aa2347a5f99ca5ad55cd1bcf98f703eb4b00badb8a8555f38b3b368db8ba7ceea94e8b219f51edce75d84166b5602156ed5962a93a51db73c59d87e906179d7a74a2a2a69d8ad99f323225c87e475d3f771b4a203a2e2b03b458401044649fa6536dfab24d7037807dcbf6518e6578
|
||||
AD: f5bb1496052a4361dddf72a288e36953a3d815d6876c013f1d6ba839e127f721b052b1f7d8ca20c7dc0386a7d459ebd7eb9fc8cb08941e6ca9ddb980f3115f65bc1928a414d441ae71dcb879d5bfe0cde0562bc37f8fde0d5291ad405c92fcbb860c43b55ac0fe663b54b3d0616aca13a5c82b7b5d34125a05c2acb5530141030e6f2aa0c8322b2c8fa307e7518918e550e9f48921c6168f094d8758e16b9f815fd0458095c4143f0922adb1840d0e685636825a9c90ee90ee537f4b8dceecbc4287c82dc9a00d7e51671e37ea284ee3ca501b1b2596459d3f592f70186f41125739e342c9f6be9241973b1414dfe5fb8cba1af82e679278cfcf95420df0c5364af4d7e72ad57d5c871fcbc35462
|
||||
CT: 7a3bf3e3ad5ae3ab71fb1f7121c3d8fb511099484b50af7ca128ee0337ed4b828dc4cde0b88dc1e8089101fa82c9beb3eb48fdcf0f5b16da441f5a3fce9a590022af95a94aed6a3e71e505f60f303c78c356f274ea85a55354078530664ecda32c80e77dc20974b3b38f4825b8fbee8c3970769a2f42c5181608a8d7d76ef4d093961b665ee42b9708fcafe2c82d3a307173e2a25ad2528c3bf83352b9265e45b70722d7cf8c9b80826d21335234ee3db69d0d37871c83222365900c96c17a7e9f5742d0bfe383be24d0d44590d4b0f29f7abe0c65daaffb968b3f2657b1eb300534eacb52ec7a6b6f9f57a50a91b1799f491361cf613c934b7f520dc4eeeb40ffc45e10be0a95e76f366d4eac14
|
||||
TAG: f613b65226afb64c614fe60d9c71ed74
|
||||
|
||||
KEY: 2f0f4631ab1c1bcf8f3ad0559c818d50e0af7d8cd63faa357f2069f30881d9cb
|
||||
NONCE: 7d0ced2fdb1c9173
|
||||
IN: 6516ba1d29357144eebfa486d21decf223da3aa76ec29bbfcbe7f1eeaf4a847710e5080177f7e5a7c8b4752c219b1cc70aef4db861ba67d0fa6222d9f4a1dc756a0ba44e62906f9374a960c16198866d867854d88f528a60e212eb91645787e75685b2e215c0a41990abc344a77236ec0186ba63a664592938cc5a8ac1d3eb99c95ce00e19fbe249263083d85b052d48bfdffc01585dc57bb2a2c6c4a819604c1ec0548c6f0f78dc05e4418b36277dc07233c7532f9c289d6aed0cc6bc7df4fd0a536c497b982e2dad2c30d2db1c6545a845c5dfa83a4ac49ef06fc9c919079d3e299e31b5c3be370814ae5022ae469d3ee55246a41bd0dc4e64351cc38c3c09af0a1aee3b388a6892deff0df3f93cd92d722b
|
||||
AD: 1ccfa1ececc8de1e200d0ecc19dcf67b7c96bea3a282c2bccba61035db5c14776387b8b8f58e5757deb0129d4e5e315f64df354a5985d2e47ebbbeafe0c914f7cf1d63dd0311ace19e69a8b6ff0ab25cc8df0408d22132205e89e5eb679268d82b2913e64e3f885bbf4a6d379b760b94590e3140dd7275ab4713cb56d0b716e2718f11316640cb394802862d39e77a46d0c065af3caf7dec14e887039d8aa8c3d3a8ac1ee06026f49d00b2f59d971b54735e95a51f199389a93a4fc24ebaba1f7a2eef7412f61febf79084fbf481afc6fb6b204084e5ef5df71f30506459dea074f11fc055cd2a8c0fc922c4811a849984352a56a15659b7d07a4cc90b88623638ea00c4c8bc13884df2237b359f2877aa41d6
|
||||
CT: e580093789ba17ffb46672dc326f09278aca08598d3e5458eaa53e6ed45d5c71a396e35b5ea3fe7b7c0496a734d24f1c75420694be2ff095d5172fd3407794e4b99fd7c374fbe8d1564a048614d3f355bfb5866de1a53e1a51f9f5e8312253cfd82f36efaa1898c850ca0d975ad1e8b0d9597a5a9e6516fe2a3c92efb7495557a8afc3da15b0d3e2ba58f612519836946cf2d15b898320d16a026c8c00a1be2e35f0ebe68f28d91c6c45d24c3f3c157cb132fa659b7794df883d90741fa2d2afcc4f27858e13ecd41b154a35d24947ae7361170060c107d8ecacb393ea67104b60457278a392fdf1794bab97d3b02b71a4eb015eaa38a4b4c944c2bc7cd5e329da4a1ab2937a6af81a6caa5fce752331fdefd4
|
||||
TAG: 0fd7419c54bc84265ed310a3411a3f2e
|
||||
|
||||
KEY: a48b9b6df475e566aba7671fbd76772cb0eff0b12499967978ce3e25fac92feb
|
||||
NONCE: 2ccbf0d6c40cb302
|
||||
IN: 09da1cacd001dce4f7573a065a4406fe0da04ab367a2d87780a2762e168957a88d3fa78f0a4b6978d449026e5a801d32884b6e14fdaaaf864214f928ebc03dead081fee96683ebb032362d5088c4c2a3b1e242f055f2604919f4dd551db777a258cf9da6d95a2bde249247812b9efc7985cf08707620808524d6dd3079b0b63bf0f71ea5de834ccb8b7c6a97125fd6ca49148e866d3134bbf1d8a6b714e9a80fe549c8bfefe342f41be2ba2300e0028f78cefab65274632dfdbe70bf7d655ec4036df561f2d4fc4d56a482bbe2f9f2ae279b3aa216b39afee75e53602de319484db89a51e844f38c361634e474f8f1f01c340f3f3594860d671346449c6d08ee38de22d246309bc7e4a252a29c86aa6d94b5b4fa58904c70
|
||||
AD: 1c2503d5aa1aad193f0da12874074ea0432bb76a61cd43a3017061514da0759846a0f3ae3a49fdb0b6d29f713de665beacb6568f2694112ca380d13f3c1698316866a7a7f87f1d7503a92176ab84fc08977b46ba664508a858e7525753c45511b3d2f407d5e993c6ede77f13d12975707e5195704970a89f71fc30828049f92f944f3aa93d6a5297e678e08952919beb7eac5919df1919cab3c3da6aa696a1eeab6371f310f7e81143e7d240b0213ae554524b52000306160dd4877bf13ba0f13bbe867da7c7d707f31335eef4cd942938ac890a0829ec66bd30ae01a2188a6e5ea0f17cd7dc875e17f03c0ab5dd18e36db8a1fc1f72859ee046b62368f168b3bea2234e0432c07b7d8e1b9277f21e692c513b9e816e6860
|
||||
CT: 7d35cfe4be56bd6e0e09dedcd01735b915bc1891a4d1f6a541abc4bcd0ebe89dcb8e365e5813742e8ec65777b6159422fada747da99394252baf8a046fc1b60ad79755f545f4448627b7acaf403000894f5641e78d3f946dfca29ec617f0660dcd6e8d8827e67e1022a245c595d86e60fbd176bf721b171bbe5ecaf4ae671b9f3dd3920146e6ad431bd8fc431820e19454b6ca209723d80fdbee187fca9c937c979206ae97be55f6ba7366a5608770a11d537396485eb0a66586385f4d4cf3905d1fc90831c3e136d5d513fa22be285193142994a3ed477145bacdcbdd791e8b3b88b0d4f1d18b27382550a818c4fd8884bf36f677c6c3ff5677406e510911e696af75e5b3f859bef699bdd16e6215fdb98d874025eada50
|
||||
TAG: 2aabff35611b3e0013f6ae0df130799b
|
||||
|
||||
KEY: 923d4b086b9e43b986f7b65e4cea6113a3d8aabefa89323c5e4d5b6f158bb7e0
|
||||
NONCE: a0f73297b87f5deb
|
||||
IN: 21435e8d5c8edf0684f58c2cba4070c10b4801adf46b6c4d322eb3990a38a9ad338ad704b9df6597f3e68d66cd5b56290c8466db2231e56d6bcb9c44e1bd081f42ca2a894dad369df2bd0d2c63d6c881732d6ea22bb22b5bc9a62eaffa1b094d0845f6b966d2cb095e7b3b8bcbc15e707449d35c8df4aea30c3b7243e977fffd59c80f1c5c9af4bb5a54b9c786fbbe8d21b2b906a87a786caed841a34a3e0cc0ac3209d83c58afba19edd63622dd261532d2cfb0b49d527d8eaa0887a087f5129d897f665264b229f860363d71a88b7d49c8dc6360182b357b0662391bb41337f46010ac32b9fada2d60a2efcb99365d3b27b7ac396900d1c821d0df8b86cc9cc1f2673259a33efea610bf8e1d00d7e9db2afea21da8f58c55f799999d
|
||||
AD: c853a8b39c0dc597d562f123cd221e4104b65423a062a4f4ba890ba344feb84290f61817e23330c365f58c3583ce08360d3c1171982ead5496d525ac878f23a57480a6ee39d4e65afd6268245bb982a2545fa1195427cdbbcd404cdad5198f55cce2a5a028fae435f71b15921d066e8d43766c32b2f2c3f57c0674e129607dcd3703eca529414adaee79d81fed432153cceb6f3fc53404810d8ec878f7d94be5d379d0e0e1aa9bc404b4b5d396038a9d76a5ce53c9f3759b8e50fb331858ca58cee81bfc3ee58baef5d19c402a3dc8b36370ec1ace5a4aa2527fb94b4f933a4ab8ccaaf6a5af5a779eae5667c2a24ab027e781c8d4f30c377aa5885a2fdaf6507d18cd824a847c35368b4ea984d2c3c3824a5b8ba3042e1852504a21a3
|
||||
CT: f2e21052eebbb86a4f5e803360855d8632aa727dca6f5e79dd74d7aff106e442001928d113005b030f8446f8eff2ee951db663978abe43090dd5ad2c51ba97a0ecf988c607d95e486d02524f690fa3c28d5c48c1f75c1f555e7b43fe7e46f2ca2b9fdb408ec4ba18b6cdde2af673183cb7b1a3c23ae77eddd4cac75e1ea14743fc571f8d31ce2e96787524cd48aadaa474181c096a032184574ddc25a6e0ac8441c212bc36298708e33c963ae931e6c6241d1affeef7b6ef759495df44b6ab647447693cf703569e69aa72f1def9a342b8978c1edea9703a421ca75b92cac4de14b88c693200022b8a2ed22b1c4678b99f4d695e080dd1196d7168e14f0d0f8ff880d742e97b9f6d00af1f7118e10b77c5ef3ea6c52f84a20fd6ea46dc
|
||||
TAG: fa8ee13400fb3f63b899df582f2fec45
|
||||
|
||||
KEY: df73adab2768559ea983cce85453fe81d79be3b3c57f202b31b94d6635cf2e4b
|
||||
NONCE: e7a87e6bf6b5a354
|
||||
IN: 0032a37abf661faa18c587fd2aa88885c061deeba81105dd221969bed5d59c7204b09b1a8c4c8de3b9f748c7fc70626ebeaca060233a57b102221b1bf0f3d9fdaaad3d2b1439c24d08f9c67f49f3c47128f92ee530abf4c4f4573bc60ae4b38109f55bca3ca9e1ba9f9fd6e34ba0d174892977a53356e1f5c88c614fe3ff3b3dd0818e7a2285412e3b37444bbe8a80942efcfd03958809a6966cda9430b2f0c9e552f4bced6e19eb3e85fc5758bd7b588297ccbed37ed94c3adc8c08ea8b058462aac9d57a939ec711bc4ecfec944d2b653b7cfc7b02a65d7057c9fdadd51b9da8cc4a3c68dae9da8b9c5319c1a2baa3d6c891c5ac4a39461484b5a01abc64df447ada24c04a4363e605eaccf339a9aa515e724206206da6d22bbd2f52e64cd7c895
|
||||
AD: f833e5ab4f8bc89167f80f576b1d6b22cdd0e30721f5f735799746cf645b6eff531d4c7b03584f3dfcb73cbd35ac42736216dc7f0de098a4f42c61ceb4b227ee288e47d697a0a76afc762f084e8fdbf9351c28340c324771c109a469341ab10ca10483ed2af5e878d7d3dc2bced2f72da3d1a25852b103ee9878e8158eb4309c1ce528f3a178ace153b6d3ae0af0d577cb3cb1540489e80427f792217ad8a09b84f027fca7ceb651b4264e98e94b4cb8a37b133390897233e8ba9103628d05b9609e8552c4a4b11e3f2fa8d56af36957390e88cba44656be3edace798cf8cdf7771bac338a256bc3cba6df97728f222f423ca7c6d149c9372d66163a98f79a234b00d4b75fb2ec860dcc2d1998105e4b9c01d68f079f3e0aa21cc534047fc7b858f8
|
||||
CT: b842eadfdf431c135bd6581d3eccae54e2267d8890036aa33dfe2d2d9715c44625441210a3a0d666d708d30588fe851ec36e10d8fa3584ed77b095149494b7c54379d62c8935e1d2b9a8f47e4759ad0b3437fdf2cc2fb6c5ea25ad10e0bdc9dc5b0517fc237eb783cc461c46665e2b1d1a5b8008dbf409ea2a63fea0276de23a32c99d92a498807a0f95e208fc6262321a78aafaf0cc3f833fff37bd4efa66f6023a25cdc6702cee3912799563d908a5183c9956a06aa71085d855dc7c809ed6e2889592b361ab3ab39060f8e419152187a794a19c2a1128882201900ea2cd597860674bf78d9720643df8701676718fd201baed4935a88e50558daf86edd08a9ab227ac7afae55c974b68de8dacad4a4d79b13ed6dfe74017a4cb9148e033436fb6
|
||||
TAG: 184095b7a8190abec08bb72d19eeb103
|
||||
|
||||
KEY: 55a4be2448b464c2ea52a2f2664ed6aba865c14ea1fea77f4689331fd105c8d4
|
||||
NONCE: db37c0a405b4626d
|
||||
IN: d266e66272e5d3462081b004cb42429c8b9741e9f678153754d726f6f9aa513464763c5e793b482fe512fece97585f1426120d4cefb3d0a8cc0a8db4bde93fc72c78f44d4fecca14650c660d3e285b327e7cdd813063e7e867b8a2d059a41bab70432b7f857199894da90dca3fe5272bae1ec694a1a07b60b05df275784d4975637e4673109f3ba846dfd1a048b202ed8e89973be608b91ee4743b1e759900f1443038951fe6189e806638985f3c16338c3c60695df58e621154d79bb973859c4558e9dca90470f77c73f004443ad5db0717abbe43266f90e57397b83ac34d1fef2e897e2483d5bcdcb627abd64b0d1aef525835f25e76d6e9158232cdde6dce970b59f58de8a98e653be32fb58edabbcefa5065d73afdf1c9c4fbf50c1022bd22bfcb98e4b422
|
||||
AD: fd6a3fdd879f8880843eac20ae01c1b9dc3487d270a806572088ef2ddc1f1e0de495e71d4813bf5c501ad31e5d791c4b5b3a0a71b63fdddcc8de4b056064ef467989ecccc5d0160d403bf3a025d4892b3b1de3e062bc3581d4410f273338311eb4637529e4a680a6e4a5e26e308630a5b6d49ead6d543f8f2bf9050aa94ce091318721e1d8b96e279f34b9759b65037bec4bf6ccda6929705aeeeebe49e327e4d7a916620c9faf3765120658af34c53fbb97ec07657b3f088fcbdc401aa7949ddeda34d885018c2c23f4f0bb8218bf0d4fc90643658b4d8834f4a8c08e590c2a790995baa9e77627c342d283e454f84fcc05be15e9627a2d9be340c9d72f222bbdfc47905f56616cd9f936d49e4732f319f020513340fb8b22828db251b102b6b137c9533936d6
|
||||
CT: bd11ed07b7b4b30eeaf25d6a41a549cca0a5aee71f990ac566a37265d7af2ce3c03703427ee0b2755c2bdfc29f9d826aec6ee4ad28af48079ac23db16580b97424f3a4e35cc23625d39f95699d9ff5143e9a2bc26fcfee4f125f5aa2d968ccfc2faaf9db3c28850f6757f735cbc50c94c498bcde4f23bffafa8dd5f70d1a011e35eb26e905d4e68848fedebeb197be595c085ba33f11ba8398258445051751888e9bba111f800f31b37c447074ca6dce6d54b4dfad6cee5138643d4f6ac045e8047248924e88ea4294c7878bc22c9b41924ce301f22693c33733107bf1ba85e34806c5e4366ea66fc52a5f89dd9bf213239158b3d4d2600dde696c61d76c398b9bf10de9118e812e891c8f3355c0ecc6405f79bc32a58905e37888a1d8395fbedc3ac54eca569f
|
||||
TAG: f7d3b58a34a86e99267e5db206f17bbe
|
||||
|
||||
KEY: 3304e4917ad7777b86c26a636292c9cc4c10d32003c49e07209eb0ef8505031a
|
||||
NONCE: 4d572d116fbd8c4d
|
||||
IN: 2f242c2ba33790ecef862b0e077ff8b15eb9d10cf2ff621ed65902494431dcbd
|
||||
AD: e699bbf250cdd93d229d0740e433897e2d19132e2b722df8b69bb6a7c2cf3b93
|
||||
CT: fb81e30436e437c7f686f86b1b65c73549a9d09db810d320785c3634934150b3
|
||||
TAG: 8b
|
||||
|
||||
KEY: ed6057bb163f1609ff28b938122f495e3d5ae4ec3dbd7456c9b5c82e28e952dc
|
||||
NONCE: e6ff6852f3a3afde
|
||||
IN: 3c50edc967eb0b3b2355f6400e0a036e796c8b7d72c5e583a86e820d53e76c43
|
||||
AD: 2441db55148e14e9e241d68296eb60d529408f0534143089671bce546db96d88
|
||||
CT: 6ecabccee31519374d4bed11296e7483d1cb759bea3f4446a96bda8b4ca6d7ac
|
||||
TAG: 355f
|
||||
|
||||
KEY: 73568183c1f9725af30e0f2067606ce802c3fe3ab5cff8d02b3db8c35176ee0d
|
||||
NONCE: 0bc9e19321b3d00a
|
||||
IN: ec2590af5ccd226a32ff750c1b029c11e3dd76c469a5579da9418e4c3fdc0d41
|
||||
AD: df30160ae0cbf2cf8992221bd62dffe691dd602afa784ca691479e957af3acf1
|
||||
CT: 9e8d8ac30626f8b831448d6976933aa5bb8c6dbc794e1f4b7eeb0e4a59342c07
|
||||
TAG: 9fd36a
|
||||
|
||||
KEY: 273bcb3f8c067da4ec3418799ad40e7e4aee74ad7e629499d646df4a7e585025
|
||||
NONCE: f60be3eb894b4030
|
||||
IN: 697498ba964d5ef401da4d94844fab1efc635e7157d0831a325bb5a4cf1fbd34
|
||||
AD: 9129715deab14f02c76ba8172571b1fa9d50365cd795bfccdfc28e7e7b4f66fc
|
||||
CT: bd4cd5af83be1c13933302675d9fcaf1c4cacdf269f6ff441d1ea2211c54e7ed
|
||||
TAG: 7ab12a37
|
||||
|
||||
KEY: ad39610c2e6a6d0961207390e076e972c2edadca885c92965fa648b2ce34fdbf
|
||||
NONCE: a90db690bba83b78
|
||||
IN: 31c49e3cd3d80a82e6b90316dfb94b38b8a23042519bf40c8181fec873c99002
|
||||
AD: ddbd7d821d18d44c66295abf245b227b5cf4366811b7b34c07679600abdbfc29
|
||||
CT: 94628fc303a0546edd51e966f2bd87968f37800c607d5e5a91f727fc1fec406f
|
||||
TAG: c22ec4e4c8
|
||||
|
||||
KEY: 29984954060ba06ece1bcfc0e50195f4632c6df48da1e02ae6c14f7065668971
|
||||
NONCE: cce53a25aeeaf747
|
||||
IN: b9b87433a9894f3c9ca8212623d62369a565a2edcddd276e07d611eda3597426
|
||||
AD: 19fa9aa59697559d8b46d9cd49c3b763c0b73b26b9e334a3eeac2c86fdbaca8d
|
||||
CT: b68c83397770c36f073710882fa86d43b0e54e8efef0ff75075604d0d7ec4e1b
|
||||
TAG: 40d4ab752f3d
|
||||
|
||||
KEY: 5c3b838b84100b2a818c0842e9fe19a7c50cf5f3ea73364c816ef588e500ff3f
|
||||
NONCE: fdf6b0229e4bcc2a
|
||||
IN: 2ba91904c143be99297b39f52856904af41705c176c8c6554b6bc89bddffbcc1
|
||||
AD: 3539d9dd821f004f4ced1637071f4be6abd7fe98f017f0a8ce3f49dc8d496f46
|
||||
CT: ff9d6d924e737a1df8c2bd3047e40ab401f903aa0e5b51acb991bac38ac2cc4d
|
||||
TAG: 1bcaa415a6a3c7
|
||||
|
||||
KEY: 6d65e627cab6d5eb1a088b25bd6c3a8a004a7a19cccae909d62fed3559c812f7
|
||||
NONCE: 7ff00a8798b792de
|
||||
IN: 6848ee4ac820291a2e1dc3baad97f1ad8b7160dfeaa1bc83b2700ae42b5a366b
|
||||
AD: d2437b1306bf0ea211449fac863ca0d1074d84caee9009c5d54b9e9bdc8de6b1
|
||||
CT: 2da0abe2a71e1c0b1ab309c160a8cebe45c6e16170aa5561806484ba2b5b9a9a
|
||||
TAG: 566003e1f78d2a90
|
||||
|
||||
KEY: 63401046a96efbc8c6483a2c396b2a593d3fae0db565525b85999fae13a46b6a
|
||||
NONCE: 051393d775e635ee
|
||||
IN: 2b4b6477580382aae782f8b5772c0948a444d8d95caacd85c0856c7e4393fe09
|
||||
AD: 3d84d2e70e9c062d1f511eb685a9a90c8d5fa50eadf8455c7148666b3e7155e0
|
||||
CT: 880c1123e54fd8ffb3c293720dd174913572e619ef46504cdaa64fc451b0ec1c
|
||||
TAG: 339274339c88d50ac0
|
||||
|
||||
KEY: 291fccfce0782f1787d62d4b9293d2ada4c04d37a8288ba9ba9aae0d31aad204
|
||||
NONCE: 7450bbd62e4aba7b
|
||||
IN: adc251e793181e5d4c4bd983b853eb13f2096ccb340996b6eca4cd2157efcec7
|
||||
AD: 4c598f6deedc8c1d97da33654763495cca3517430eec4edb006b10c95e031ae6
|
||||
CT: 28bda22e4922cd8ff6739cd8a6bdafce036d9c61a145a65ca1b86f6d4d3206a1
|
||||
TAG: d98fd43fe7ac74d4b016
|
||||
|
||||
KEY: fa3a9674d4a0eb36b2f7547c956443d09e6b4e4acfc9deda838eb7ebdb999a8d
|
||||
NONCE: 0a2572592c3bbbf6
|
||||
IN: ae27f70fda9f5a5be0f704a27f0b8a9c04ce83d3c2e0d7ec152da25f473b0c8a
|
||||
AD: 6ee8705a9a3655d198497ad410da02005872ecbe397824851b80f4050bfdd311
|
||||
CT: f356cbd88e4e2aff62d91e3f914032085388955bbba995fde013758b8702e38f
|
||||
TAG: 00324c76fecd3f50e1e3b8
|
||||
|
||||
KEY: 471ec87b992b104d369748d96856b5f66149cb45ca05c17f29d24eb9526fe6db
|
||||
NONCE: 23a2df9ed0b47439
|
||||
IN: 2b9452bca0f48e5519ec3d0736597608df6ad9ce799eba913cff71573d79c092
|
||||
AD: a56722ddfaee5f1b64398c225ee8bcdcfde5c2127101c363bfac52bc409c1082
|
||||
CT: 7bbc464aac5dd29c25262fe0b116c176d827c2cc8dd63428393b0a9110f3c194
|
||||
TAG: 2e87f4a6663a62e47c7e197f
|
||||
|
||||
KEY: a29d1cfd4ccdc18803fbca9500f4bb29ce99cfcbf8acc41b8208dae4b7ee5d64
|
||||
NONCE: 634f99e88e237ef0
|
||||
IN: 09ee5982c5743f396d0c29c13e3fbb8fb89f61705da05466291e010effd51a5c
|
||||
AD: 564dddfcc3227b413244f1105b610f192decf15c4cfa067f4d7fcd6bd7af11b8
|
||||
CT: 32916b67a6f32733623344c98c49773f3e721dc2ded105fb245799525bc9c84c
|
||||
TAG: ff463c07e7ef831321d3fd775f
|
||||
|
||||
KEY: 08ba23616d911188f91da063278bef1237dcbf17f52585e53c2c4b6cf3ac9f0d
|
||||
NONCE: 989ae593eddd3874
|
||||
IN: 749152c9478944c8271c0c11e07bc1c569eec01493e65b3b94842a1bf5d721f8
|
||||
AD: a12d1a45b7c9b91ab08751a70b753714052ad24e0b2619fe8c3be303c65f2dbc
|
||||
CT: 34c40538ee1d22ddf8ac290dd7d423dfc622b5cf8f3412a5343e277822aea713
|
||||
TAG: 014c7c678e0949e88071d1fe3531
|
||||
|
||||
KEY: c2ba8bed8634156afc6bfe3754c91744d4131de39d059f3a866399f916553b5c
|
||||
NONCE: 80fbf7b433a4cd9c
|
||||
IN: 419be6623e7964f9f26068dd969e4a139617e67c5ffb269b3013c433fe771c77
|
||||
AD: 3937592db78a61ff469691b6800792019bc2b3d42512f23c1b1a66a8274495cb
|
||||
CT: 9d5bd1c7e766763eb00684c038043111d8c6390a8d6e17a15ef97c02ab16f09c
|
||||
TAG: a64d0eeb4a01481ec0cee8c1c357e3
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,482 +0,0 @@
|
||||
/* ====================================================================
|
||||
* Copyright (c) 2012 The OpenSSL Project. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. All advertising materials mentioning features or use of this
|
||||
* software must display the following acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
|
||||
*
|
||||
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
|
||||
* endorse or promote products derived from this software without
|
||||
* prior written permission. For written permission, please contact
|
||||
* openssl-core@openssl.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "OpenSSL"
|
||||
* nor may "OpenSSL" appear in their names without prior written
|
||||
* permission of the OpenSSL Project.
|
||||
*
|
||||
* 6. Redistributions of any form whatsoever must retain the following
|
||||
* acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit (http://www.openssl.org/)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
|
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ====================================================================
|
||||
*
|
||||
* This product includes cryptographic software written by Eric Young
|
||||
* (eay@cryptsoft.com). This product includes software written by Tim
|
||||
* Hudson (tjh@cryptsoft.com). */
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl/digest.h>
|
||||
#include <openssl/nid.h>
|
||||
#include <openssl/sha.h>
|
||||
|
||||
#include "../internal.h"
|
||||
#include "internal.h"
|
||||
|
||||
|
||||
/* TODO(davidben): unsigned should be size_t. The various constant_time
|
||||
* functions need to be switched to size_t. */
|
||||
|
||||
/* MAX_HASH_BIT_COUNT_BYTES is the maximum number of bytes in the hash's length
|
||||
* field. (SHA-384/512 have 128-bit length.) */
|
||||
#define MAX_HASH_BIT_COUNT_BYTES 16
|
||||
|
||||
/* MAX_HASH_BLOCK_SIZE is the maximum hash block size that we'll support.
|
||||
* Currently SHA-384/512 has a 128-byte block size and that's the largest
|
||||
* supported by TLS.) */
|
||||
#define MAX_HASH_BLOCK_SIZE 128
|
||||
|
||||
int EVP_tls_cbc_remove_padding(unsigned *out_padding_ok, unsigned *out_len,
|
||||
const uint8_t *in, unsigned in_len,
|
||||
unsigned block_size, unsigned mac_size) {
|
||||
unsigned padding_length, good, to_check, i;
|
||||
const unsigned overhead = 1 /* padding length byte */ + mac_size;
|
||||
|
||||
/* These lengths are all public so we can test them in non-constant time. */
|
||||
if (overhead > in_len) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
padding_length = in[in_len - 1];
|
||||
|
||||
good = constant_time_ge(in_len, overhead + padding_length);
|
||||
/* The padding consists of a length byte at the end of the record and
|
||||
* then that many bytes of padding, all with the same value as the
|
||||
* length byte. Thus, with the length byte included, there are i+1
|
||||
* bytes of padding.
|
||||
*
|
||||
* We can't check just |padding_length+1| bytes because that leaks
|
||||
* decrypted information. Therefore we always have to check the maximum
|
||||
* amount of padding possible. (Again, the length of the record is
|
||||
* public information so we can use it.) */
|
||||
to_check = 256; /* maximum amount of padding, inc length byte. */
|
||||
if (to_check > in_len) {
|
||||
to_check = in_len;
|
||||
}
|
||||
|
||||
for (i = 0; i < to_check; i++) {
|
||||
uint8_t mask = constant_time_ge_8(padding_length, i);
|
||||
uint8_t b = in[in_len - 1 - i];
|
||||
/* The final |padding_length+1| bytes should all have the value
|
||||
* |padding_length|. Therefore the XOR should be zero. */
|
||||
good &= ~(mask & (padding_length ^ b));
|
||||
}
|
||||
|
||||
/* If any of the final |padding_length+1| bytes had the wrong value,
|
||||
* one or more of the lower eight bits of |good| will be cleared. */
|
||||
good = constant_time_eq(0xff, good & 0xff);
|
||||
|
||||
/* Always treat |padding_length| as zero on error. If, assuming block size of
|
||||
* 16, a padding of [<15 arbitrary bytes> 15] treated |padding_length| as 16
|
||||
* and returned -1, distinguishing good MAC and bad padding from bad MAC and
|
||||
* bad padding would give POODLE's padding oracle. */
|
||||
padding_length = good & (padding_length + 1);
|
||||
*out_len = in_len - padding_length;
|
||||
*out_padding_ok = good;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void EVP_tls_cbc_copy_mac(uint8_t *out, unsigned md_size,
|
||||
const uint8_t *in, unsigned in_len,
|
||||
unsigned orig_len) {
|
||||
uint8_t rotated_mac1[EVP_MAX_MD_SIZE], rotated_mac2[EVP_MAX_MD_SIZE];
|
||||
uint8_t *rotated_mac = rotated_mac1;
|
||||
uint8_t *rotated_mac_tmp = rotated_mac2;
|
||||
|
||||
/* mac_end is the index of |in| just after the end of the MAC. */
|
||||
unsigned mac_end = in_len;
|
||||
unsigned mac_start = mac_end - md_size;
|
||||
|
||||
assert(orig_len >= in_len);
|
||||
assert(in_len >= md_size);
|
||||
assert(md_size <= EVP_MAX_MD_SIZE);
|
||||
|
||||
/* scan_start contains the number of bytes that we can ignore because
|
||||
* the MAC's position can only vary by 255 bytes. */
|
||||
unsigned scan_start = 0;
|
||||
/* This information is public so it's safe to branch based on it. */
|
||||
if (orig_len > md_size + 255 + 1) {
|
||||
scan_start = orig_len - (md_size + 255 + 1);
|
||||
}
|
||||
|
||||
unsigned rotate_offset = 0;
|
||||
uint8_t mac_started = 0;
|
||||
OPENSSL_memset(rotated_mac, 0, md_size);
|
||||
for (unsigned i = scan_start, j = 0; i < orig_len; i++, j++) {
|
||||
if (j >= md_size) {
|
||||
j -= md_size;
|
||||
}
|
||||
unsigned is_mac_start = constant_time_eq(i, mac_start);
|
||||
mac_started |= is_mac_start;
|
||||
uint8_t mac_ended = constant_time_ge_8(i, mac_end);
|
||||
rotated_mac[j] |= in[i] & mac_started & ~mac_ended;
|
||||
/* Save the offset that |mac_start| is mapped to. */
|
||||
rotate_offset |= j & is_mac_start;
|
||||
}
|
||||
|
||||
/* Now rotate the MAC. We rotate in log(md_size) steps, one for each bit
|
||||
* position. */
|
||||
for (unsigned offset = 1; offset < md_size;
|
||||
offset <<= 1, rotate_offset >>= 1) {
|
||||
/* Rotate by |offset| iff the corresponding bit is set in
|
||||
* |rotate_offset|, placing the result in |rotated_mac_tmp|. */
|
||||
const uint8_t skip_rotate = (rotate_offset & 1) - 1;
|
||||
for (unsigned i = 0, j = offset; i < md_size; i++, j++) {
|
||||
if (j >= md_size) {
|
||||
j -= md_size;
|
||||
}
|
||||
rotated_mac_tmp[i] =
|
||||
constant_time_select_8(skip_rotate, rotated_mac[i], rotated_mac[j]);
|
||||
}
|
||||
|
||||
/* Swap pointers so |rotated_mac| contains the (possibly) rotated value.
|
||||
* Note the number of iterations and thus the identity of these pointers is
|
||||
* public information. */
|
||||
uint8_t *tmp = rotated_mac;
|
||||
rotated_mac = rotated_mac_tmp;
|
||||
rotated_mac_tmp = tmp;
|
||||
}
|
||||
|
||||
OPENSSL_memcpy(out, rotated_mac, md_size);
|
||||
}
|
||||
|
||||
/* u32toBE serialises an unsigned, 32-bit number (n) as four bytes at (p) in
|
||||
* big-endian order. The value of p is advanced by four. */
|
||||
#define u32toBE(n, p) \
|
||||
do { \
|
||||
*((p)++) = (uint8_t)((n) >> 24); \
|
||||
*((p)++) = (uint8_t)((n) >> 16); \
|
||||
*((p)++) = (uint8_t)((n) >> 8); \
|
||||
*((p)++) = (uint8_t)((n)); \
|
||||
} while (0)
|
||||
|
||||
/* u64toBE serialises an unsigned, 64-bit number (n) as eight bytes at (p) in
|
||||
* big-endian order. The value of p is advanced by eight. */
|
||||
#define u64toBE(n, p) \
|
||||
do { \
|
||||
*((p)++) = (uint8_t)((n) >> 56); \
|
||||
*((p)++) = (uint8_t)((n) >> 48); \
|
||||
*((p)++) = (uint8_t)((n) >> 40); \
|
||||
*((p)++) = (uint8_t)((n) >> 32); \
|
||||
*((p)++) = (uint8_t)((n) >> 24); \
|
||||
*((p)++) = (uint8_t)((n) >> 16); \
|
||||
*((p)++) = (uint8_t)((n) >> 8); \
|
||||
*((p)++) = (uint8_t)((n)); \
|
||||
} while (0)
|
||||
|
||||
/* These functions serialize the state of a hash and thus perform the standard
|
||||
* "final" operation without adding the padding and length that such a function
|
||||
* typically does. */
|
||||
static void tls1_sha1_final_raw(void *ctx, uint8_t *md_out) {
|
||||
SHA_CTX *sha1 = ctx;
|
||||
u32toBE(sha1->h[0], md_out);
|
||||
u32toBE(sha1->h[1], md_out);
|
||||
u32toBE(sha1->h[2], md_out);
|
||||
u32toBE(sha1->h[3], md_out);
|
||||
u32toBE(sha1->h[4], md_out);
|
||||
}
|
||||
#define LARGEST_DIGEST_CTX SHA_CTX
|
||||
|
||||
static void tls1_sha256_final_raw(void *ctx, uint8_t *md_out) {
|
||||
SHA256_CTX *sha256 = ctx;
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
u32toBE(sha256->h[i], md_out);
|
||||
}
|
||||
}
|
||||
#undef LARGEST_DIGEST_CTX
|
||||
#define LARGEST_DIGEST_CTX SHA256_CTX
|
||||
|
||||
static void tls1_sha512_final_raw(void *ctx, uint8_t *md_out) {
|
||||
SHA512_CTX *sha512 = ctx;
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
u64toBE(sha512->h[i], md_out);
|
||||
}
|
||||
}
|
||||
#undef LARGEST_DIGEST_CTX
|
||||
#define LARGEST_DIGEST_CTX SHA512_CTX
|
||||
|
||||
int EVP_tls_cbc_record_digest_supported(const EVP_MD *md) {
|
||||
switch (EVP_MD_type(md)) {
|
||||
case NID_sha1:
|
||||
case NID_sha256:
|
||||
case NID_sha384:
|
||||
return 1;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int EVP_tls_cbc_digest_record(const EVP_MD *md, uint8_t *md_out,
|
||||
size_t *md_out_size, const uint8_t header[13],
|
||||
const uint8_t *data, size_t data_plus_mac_size,
|
||||
size_t data_plus_mac_plus_padding_size,
|
||||
const uint8_t *mac_secret,
|
||||
unsigned mac_secret_length) {
|
||||
union {
|
||||
double align;
|
||||
uint8_t c[sizeof(LARGEST_DIGEST_CTX)];
|
||||
} md_state;
|
||||
void (*md_final_raw)(void *ctx, uint8_t *md_out);
|
||||
void (*md_transform)(void *ctx, const uint8_t *block);
|
||||
unsigned md_size, md_block_size = 64;
|
||||
unsigned len, max_mac_bytes, num_blocks, num_starting_blocks, k,
|
||||
mac_end_offset, c, index_a, index_b;
|
||||
unsigned int bits; /* at most 18 bits */
|
||||
uint8_t length_bytes[MAX_HASH_BIT_COUNT_BYTES];
|
||||
/* hmac_pad is the masked HMAC key. */
|
||||
uint8_t hmac_pad[MAX_HASH_BLOCK_SIZE];
|
||||
uint8_t first_block[MAX_HASH_BLOCK_SIZE];
|
||||
uint8_t mac_out[EVP_MAX_MD_SIZE];
|
||||
unsigned i, j, md_out_size_u;
|
||||
EVP_MD_CTX md_ctx;
|
||||
/* mdLengthSize is the number of bytes in the length field that terminates
|
||||
* the hash. */
|
||||
unsigned md_length_size = 8;
|
||||
|
||||
/* This is a, hopefully redundant, check that allows us to forget about
|
||||
* many possible overflows later in this function. */
|
||||
assert(data_plus_mac_plus_padding_size < 1024 * 1024);
|
||||
|
||||
switch (EVP_MD_type(md)) {
|
||||
case NID_sha1:
|
||||
SHA1_Init((SHA_CTX *)md_state.c);
|
||||
md_final_raw = tls1_sha1_final_raw;
|
||||
md_transform =
|
||||
(void (*)(void *ctx, const uint8_t *block))SHA1_Transform;
|
||||
md_size = 20;
|
||||
break;
|
||||
|
||||
case NID_sha256:
|
||||
SHA256_Init((SHA256_CTX *)md_state.c);
|
||||
md_final_raw = tls1_sha256_final_raw;
|
||||
md_transform =
|
||||
(void (*)(void *ctx, const uint8_t *block))SHA256_Transform;
|
||||
md_size = 32;
|
||||
break;
|
||||
|
||||
case NID_sha384:
|
||||
SHA384_Init((SHA512_CTX *)md_state.c);
|
||||
md_final_raw = tls1_sha512_final_raw;
|
||||
md_transform =
|
||||
(void (*)(void *ctx, const uint8_t *block))SHA512_Transform;
|
||||
md_size = 384 / 8;
|
||||
md_block_size = 128;
|
||||
md_length_size = 16;
|
||||
break;
|
||||
|
||||
default:
|
||||
/* EVP_tls_cbc_record_digest_supported should have been called first to
|
||||
* check that the hash function is supported. */
|
||||
assert(0);
|
||||
*md_out_size = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
assert(md_length_size <= MAX_HASH_BIT_COUNT_BYTES);
|
||||
assert(md_block_size <= MAX_HASH_BLOCK_SIZE);
|
||||
assert(md_size <= EVP_MAX_MD_SIZE);
|
||||
|
||||
static const unsigned kHeaderLength = 13;
|
||||
|
||||
/* kVarianceBlocks is the number of blocks of the hash that we have to
|
||||
* calculate in constant time because they could be altered by the
|
||||
* padding value.
|
||||
*
|
||||
* TLSv1 has MACs up to 48 bytes long (SHA-384) and the padding is not
|
||||
* required to be minimal. Therefore we say that the final six blocks
|
||||
* can vary based on the padding. */
|
||||
static const unsigned kVarianceBlocks = 6;
|
||||
|
||||
/* From now on we're dealing with the MAC, which conceptually has 13
|
||||
* bytes of `header' before the start of the data. */
|
||||
len = data_plus_mac_plus_padding_size + kHeaderLength;
|
||||
/* max_mac_bytes contains the maximum bytes of bytes in the MAC, including
|
||||
* |header|, assuming that there's no padding. */
|
||||
max_mac_bytes = len - md_size - 1;
|
||||
/* num_blocks is the maximum number of hash blocks. */
|
||||
num_blocks =
|
||||
(max_mac_bytes + 1 + md_length_size + md_block_size - 1) / md_block_size;
|
||||
/* In order to calculate the MAC in constant time we have to handle
|
||||
* the final blocks specially because the padding value could cause the
|
||||
* end to appear somewhere in the final |kVarianceBlocks| blocks and we
|
||||
* can't leak where. However, |num_starting_blocks| worth of data can
|
||||
* be hashed right away because no padding value can affect whether
|
||||
* they are plaintext. */
|
||||
num_starting_blocks = 0;
|
||||
/* k is the starting byte offset into the conceptual header||data where
|
||||
* we start processing. */
|
||||
k = 0;
|
||||
/* mac_end_offset is the index just past the end of the data to be
|
||||
* MACed. */
|
||||
mac_end_offset = data_plus_mac_size + kHeaderLength - md_size;
|
||||
/* c is the index of the 0x80 byte in the final hash block that
|
||||
* contains application data. */
|
||||
c = mac_end_offset % md_block_size;
|
||||
/* index_a is the hash block number that contains the 0x80 terminating
|
||||
* value. */
|
||||
index_a = mac_end_offset / md_block_size;
|
||||
/* index_b is the hash block number that contains the 64-bit hash
|
||||
* length, in bits. */
|
||||
index_b = (mac_end_offset + md_length_size) / md_block_size;
|
||||
/* bits is the hash-length in bits. It includes the additional hash
|
||||
* block for the masked HMAC key. */
|
||||
|
||||
if (num_blocks > kVarianceBlocks) {
|
||||
num_starting_blocks = num_blocks - kVarianceBlocks;
|
||||
k = md_block_size * num_starting_blocks;
|
||||
}
|
||||
|
||||
bits = 8 * mac_end_offset;
|
||||
|
||||
/* Compute the initial HMAC block. */
|
||||
bits += 8 * md_block_size;
|
||||
OPENSSL_memset(hmac_pad, 0, md_block_size);
|
||||
assert(mac_secret_length <= sizeof(hmac_pad));
|
||||
OPENSSL_memcpy(hmac_pad, mac_secret, mac_secret_length);
|
||||
for (i = 0; i < md_block_size; i++) {
|
||||
hmac_pad[i] ^= 0x36;
|
||||
}
|
||||
|
||||
md_transform(md_state.c, hmac_pad);
|
||||
|
||||
OPENSSL_memset(length_bytes, 0, md_length_size - 4);
|
||||
length_bytes[md_length_size - 4] = (uint8_t)(bits >> 24);
|
||||
length_bytes[md_length_size - 3] = (uint8_t)(bits >> 16);
|
||||
length_bytes[md_length_size - 2] = (uint8_t)(bits >> 8);
|
||||
length_bytes[md_length_size - 1] = (uint8_t)bits;
|
||||
|
||||
if (k > 0) {
|
||||
/* k is a multiple of md_block_size. */
|
||||
OPENSSL_memcpy(first_block, header, 13);
|
||||
OPENSSL_memcpy(first_block + 13, data, md_block_size - 13);
|
||||
md_transform(md_state.c, first_block);
|
||||
for (i = 1; i < k / md_block_size; i++) {
|
||||
md_transform(md_state.c, data + md_block_size * i - 13);
|
||||
}
|
||||
}
|
||||
|
||||
OPENSSL_memset(mac_out, 0, sizeof(mac_out));
|
||||
|
||||
/* We now process the final hash blocks. For each block, we construct
|
||||
* it in constant time. If the |i==index_a| then we'll include the 0x80
|
||||
* bytes and zero pad etc. For each block we selectively copy it, in
|
||||
* constant time, to |mac_out|. */
|
||||
for (i = num_starting_blocks; i <= num_starting_blocks + kVarianceBlocks;
|
||||
i++) {
|
||||
uint8_t block[MAX_HASH_BLOCK_SIZE];
|
||||
uint8_t is_block_a = constant_time_eq_8(i, index_a);
|
||||
uint8_t is_block_b = constant_time_eq_8(i, index_b);
|
||||
for (j = 0; j < md_block_size; j++) {
|
||||
uint8_t b = 0, is_past_c, is_past_cp1;
|
||||
if (k < kHeaderLength) {
|
||||
b = header[k];
|
||||
} else if (k < data_plus_mac_plus_padding_size + kHeaderLength) {
|
||||
b = data[k - kHeaderLength];
|
||||
}
|
||||
k++;
|
||||
|
||||
is_past_c = is_block_a & constant_time_ge_8(j, c);
|
||||
is_past_cp1 = is_block_a & constant_time_ge_8(j, c + 1);
|
||||
/* If this is the block containing the end of the
|
||||
* application data, and we are at the offset for the
|
||||
* 0x80 value, then overwrite b with 0x80. */
|
||||
b = constant_time_select_8(is_past_c, 0x80, b);
|
||||
/* If this the the block containing the end of the
|
||||
* application data and we're past the 0x80 value then
|
||||
* just write zero. */
|
||||
b = b & ~is_past_cp1;
|
||||
/* If this is index_b (the final block), but not
|
||||
* index_a (the end of the data), then the 64-bit
|
||||
* length didn't fit into index_a and we're having to
|
||||
* add an extra block of zeros. */
|
||||
b &= ~is_block_b | is_block_a;
|
||||
|
||||
/* The final bytes of one of the blocks contains the
|
||||
* length. */
|
||||
if (j >= md_block_size - md_length_size) {
|
||||
/* If this is index_b, write a length byte. */
|
||||
b = constant_time_select_8(
|
||||
is_block_b, length_bytes[j - (md_block_size - md_length_size)], b);
|
||||
}
|
||||
block[j] = b;
|
||||
}
|
||||
|
||||
md_transform(md_state.c, block);
|
||||
md_final_raw(md_state.c, block);
|
||||
/* If this is index_b, copy the hash value to |mac_out|. */
|
||||
for (j = 0; j < md_size; j++) {
|
||||
mac_out[j] |= block[j] & is_block_b;
|
||||
}
|
||||
}
|
||||
|
||||
EVP_MD_CTX_init(&md_ctx);
|
||||
if (!EVP_DigestInit_ex(&md_ctx, md, NULL /* engine */)) {
|
||||
EVP_MD_CTX_cleanup(&md_ctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Complete the HMAC in the standard manner. */
|
||||
for (i = 0; i < md_block_size; i++) {
|
||||
hmac_pad[i] ^= 0x6a;
|
||||
}
|
||||
|
||||
EVP_DigestUpdate(&md_ctx, hmac_pad, md_block_size);
|
||||
EVP_DigestUpdate(&md_ctx, mac_out, md_size);
|
||||
EVP_DigestFinal(&md_ctx, md_out, &md_out_size_u);
|
||||
*md_out_size = md_out_size_u;
|
||||
EVP_MD_CTX_cleanup(&md_ctx);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
include_directories(../../include)
|
||||
|
||||
if (${ARCH} STREQUAL "x86_64")
|
||||
set(
|
||||
CIPHER_ARCH_SOURCES
|
||||
|
||||
aes128gcmsiv-x86_64.${ASM_EXT}
|
||||
chacha20_poly1305_x86_64.${ASM_EXT}
|
||||
)
|
||||
endif()
|
||||
|
||||
add_library(
|
||||
cipher_extra
|
||||
|
||||
OBJECT
|
||||
|
||||
cipher_extra.c
|
||||
derive_key.c
|
||||
|
||||
e_null.c
|
||||
e_rc2.c
|
||||
e_rc4.c
|
||||
e_aesgcmsiv.c
|
||||
e_aesctrhmac.c
|
||||
e_chacha20poly1305.c
|
||||
|
||||
tls_cbc.c
|
||||
e_tls.c
|
||||
e_ssl3.c
|
||||
|
||||
${CIPHER_ARCH_SOURCES}
|
||||
)
|
||||
|
||||
perlasm(aes128gcmsiv-x86_64.${ASM_EXT} asm/aes128gcmsiv-x86_64.pl)
|
||||
perlasm(chacha20_poly1305_x86_64.${ASM_EXT} asm/chacha20_poly1305_x86_64.pl)
|
||||
@@ -0,0 +1,653 @@
|
||||
/* Copyright (c) 2014, Google Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <openssl/aead.h>
|
||||
#include <openssl/cipher.h>
|
||||
#include <openssl/err.h>
|
||||
|
||||
#include "../fipsmodule/cipher/internal.h"
|
||||
#include "../internal.h"
|
||||
#include "../test/file_test.h"
|
||||
#include "../test/test_util.h"
|
||||
|
||||
|
||||
struct KnownAEAD {
|
||||
const char name[40];
|
||||
const EVP_AEAD *(*func)(void);
|
||||
const char *test_vectors;
|
||||
// limited_implementation indicates that tests that assume a generic AEAD
|
||||
// interface should not be performed. For example, the key-wrap AEADs only
|
||||
// handle inputs that are a multiple of eight bytes in length and the
|
||||
// SSLv3/TLS AEADs have the concept of “direction”.
|
||||
bool limited_implementation;
|
||||
// truncated_tags is true if the AEAD supports truncating tags to arbitrary
|
||||
// lengths.
|
||||
bool truncated_tags;
|
||||
// ad_len, if non-zero, is the required length of the AD.
|
||||
size_t ad_len;
|
||||
};
|
||||
|
||||
static const struct KnownAEAD kAEADs[] = {
|
||||
{"AES_128_GCM", EVP_aead_aes_128_gcm, "aes_128_gcm_tests.txt", false, true,
|
||||
0},
|
||||
{"AES_128_GCM_NIST", EVP_aead_aes_128_gcm, "nist_cavp/aes_128_gcm.txt",
|
||||
false, true, 0},
|
||||
{"AES_256_GCM", EVP_aead_aes_256_gcm, "aes_256_gcm_tests.txt", false, true,
|
||||
0},
|
||||
{"AES_256_GCM_NIST", EVP_aead_aes_256_gcm, "nist_cavp/aes_256_gcm.txt",
|
||||
false, true, 0},
|
||||
#if !defined(OPENSSL_SMALL)
|
||||
{"AES_128_GCM_SIV", EVP_aead_aes_128_gcm_siv, "aes_128_gcm_siv_tests.txt",
|
||||
false, false, 0},
|
||||
{"AES_256_GCM_SIV", EVP_aead_aes_256_gcm_siv, "aes_256_gcm_siv_tests.txt",
|
||||
false, false, 0},
|
||||
#endif
|
||||
{"ChaCha20Poly1305", EVP_aead_chacha20_poly1305,
|
||||
"chacha20_poly1305_tests.txt", false, true, 0},
|
||||
{"AES_128_CBC_SHA1_TLS", EVP_aead_aes_128_cbc_sha1_tls,
|
||||
"aes_128_cbc_sha1_tls_tests.txt", true, false, 11},
|
||||
{"AES_128_CBC_SHA1_TLSImplicitIV",
|
||||
EVP_aead_aes_128_cbc_sha1_tls_implicit_iv,
|
||||
"aes_128_cbc_sha1_tls_implicit_iv_tests.txt", true, false, 11},
|
||||
{"AES_128_CBC_SHA256_TLS", EVP_aead_aes_128_cbc_sha256_tls,
|
||||
"aes_128_cbc_sha256_tls_tests.txt", true, false, 11},
|
||||
{"AES_256_CBC_SHA1_TLS", EVP_aead_aes_256_cbc_sha1_tls,
|
||||
"aes_256_cbc_sha1_tls_tests.txt", true, false, 11},
|
||||
{"AES_256_CBC_SHA1_TLSImplicitIV",
|
||||
EVP_aead_aes_256_cbc_sha1_tls_implicit_iv,
|
||||
"aes_256_cbc_sha1_tls_implicit_iv_tests.txt", true, false, 11},
|
||||
{"AES_256_CBC_SHA256_TLS", EVP_aead_aes_256_cbc_sha256_tls,
|
||||
"aes_256_cbc_sha256_tls_tests.txt", true, false, 11},
|
||||
{"AES_256_CBC_SHA384_TLS", EVP_aead_aes_256_cbc_sha384_tls,
|
||||
"aes_256_cbc_sha384_tls_tests.txt", true, false, 11},
|
||||
{"DES_EDE3_CBC_SHA1_TLS", EVP_aead_des_ede3_cbc_sha1_tls,
|
||||
"des_ede3_cbc_sha1_tls_tests.txt", true, false, 11},
|
||||
{"DES_EDE3_CBC_SHA1_TLSImplicitIV",
|
||||
EVP_aead_des_ede3_cbc_sha1_tls_implicit_iv,
|
||||
"des_ede3_cbc_sha1_tls_implicit_iv_tests.txt", true, false, 11},
|
||||
{"AES_128_CBC_SHA1_SSL3", EVP_aead_aes_128_cbc_sha1_ssl3,
|
||||
"aes_128_cbc_sha1_ssl3_tests.txt", true, false, 9},
|
||||
{"AES_256_CBC_SHA1_SSL3", EVP_aead_aes_256_cbc_sha1_ssl3,
|
||||
"aes_256_cbc_sha1_ssl3_tests.txt", true, false, 9},
|
||||
{"DES_EDE3_CBC_SHA1_SSL3", EVP_aead_des_ede3_cbc_sha1_ssl3,
|
||||
"des_ede3_cbc_sha1_ssl3_tests.txt", true, false, 9},
|
||||
{"AES_128_CTR_HMAC_SHA256", EVP_aead_aes_128_ctr_hmac_sha256,
|
||||
"aes_128_ctr_hmac_sha256.txt", false, true, 0},
|
||||
{"AES_256_CTR_HMAC_SHA256", EVP_aead_aes_256_ctr_hmac_sha256,
|
||||
"aes_256_ctr_hmac_sha256.txt", false, true, 0},
|
||||
};
|
||||
|
||||
class PerAEADTest : public testing::TestWithParam<KnownAEAD> {
|
||||
public:
|
||||
const EVP_AEAD *aead() { return GetParam().func(); }
|
||||
};
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(, PerAEADTest, testing::ValuesIn(kAEADs),
|
||||
[](const testing::TestParamInfo<KnownAEAD> ¶ms)
|
||||
-> std::string { return params.param.name; });
|
||||
|
||||
// Tests an AEAD against a series of test vectors from a file, using the
|
||||
// FileTest format. As an example, here's a valid test case:
|
||||
//
|
||||
// KEY: 5a19f3173586b4c42f8412f4d5a786531b3231753e9e00998aec12fda8df10e4
|
||||
// NONCE: 978105dfce667bf4
|
||||
// IN: 6a4583908d
|
||||
// AD: b654574932
|
||||
// CT: 5294265a60
|
||||
// TAG: 1d45758621762e061368e68868e2f929
|
||||
TEST_P(PerAEADTest, TestVector) {
|
||||
std::string test_vectors = "crypto/cipher_extra/test/";
|
||||
test_vectors += GetParam().test_vectors;
|
||||
FileTestGTest(test_vectors.c_str(), [&](FileTest *t) {
|
||||
std::vector<uint8_t> key, nonce, in, ad, ct, tag;
|
||||
ASSERT_TRUE(t->GetBytes(&key, "KEY"));
|
||||
ASSERT_TRUE(t->GetBytes(&nonce, "NONCE"));
|
||||
ASSERT_TRUE(t->GetBytes(&in, "IN"));
|
||||
ASSERT_TRUE(t->GetBytes(&ad, "AD"));
|
||||
ASSERT_TRUE(t->GetBytes(&ct, "CT"));
|
||||
ASSERT_TRUE(t->GetBytes(&tag, "TAG"));
|
||||
size_t tag_len = tag.size();
|
||||
if (t->HasAttribute("TAG_LEN")) {
|
||||
// Legacy AEADs are MAC-then-encrypt and may include padding in the TAG
|
||||
// field. TAG_LEN contains the actual size of the digest in that case.
|
||||
std::string tag_len_str;
|
||||
ASSERT_TRUE(t->GetAttribute(&tag_len_str, "TAG_LEN"));
|
||||
tag_len = strtoul(tag_len_str.c_str(), nullptr, 10);
|
||||
ASSERT_TRUE(tag_len);
|
||||
}
|
||||
|
||||
bssl::ScopedEVP_AEAD_CTX ctx;
|
||||
ASSERT_TRUE(EVP_AEAD_CTX_init_with_direction(
|
||||
ctx.get(), aead(), key.data(), key.size(), tag_len, evp_aead_seal));
|
||||
|
||||
std::vector<uint8_t> out(in.size() + EVP_AEAD_max_overhead(aead()));
|
||||
if (!t->HasAttribute("NO_SEAL")) {
|
||||
size_t out_len;
|
||||
ASSERT_TRUE(EVP_AEAD_CTX_seal(ctx.get(), out.data(), &out_len, out.size(),
|
||||
nonce.data(), nonce.size(), in.data(),
|
||||
in.size(), ad.data(), ad.size()));
|
||||
out.resize(out_len);
|
||||
|
||||
ASSERT_EQ(out.size(), ct.size() + tag.size());
|
||||
EXPECT_EQ(Bytes(ct), Bytes(out.data(), ct.size()));
|
||||
EXPECT_EQ(Bytes(tag), Bytes(out.data() + ct.size(), tag.size()));
|
||||
} else {
|
||||
out.resize(ct.size() + tag.size());
|
||||
OPENSSL_memcpy(out.data(), ct.data(), ct.size());
|
||||
OPENSSL_memcpy(out.data() + ct.size(), tag.data(), tag.size());
|
||||
}
|
||||
|
||||
// The "stateful" AEADs for implementing pre-AEAD cipher suites need to be
|
||||
// reset after each operation.
|
||||
ctx.Reset();
|
||||
ASSERT_TRUE(EVP_AEAD_CTX_init_with_direction(
|
||||
ctx.get(), aead(), key.data(), key.size(), tag_len, evp_aead_open));
|
||||
|
||||
std::vector<uint8_t> out2(out.size());
|
||||
size_t out2_len;
|
||||
int ret = EVP_AEAD_CTX_open(ctx.get(), out2.data(), &out2_len, out2.size(),
|
||||
nonce.data(), nonce.size(), out.data(),
|
||||
out.size(), ad.data(), ad.size());
|
||||
if (t->HasAttribute("FAILS")) {
|
||||
ASSERT_FALSE(ret) << "Decrypted bad data.";
|
||||
ERR_clear_error();
|
||||
return;
|
||||
}
|
||||
|
||||
ASSERT_TRUE(ret) << "Failed to decrypt.";
|
||||
out2.resize(out2_len);
|
||||
EXPECT_EQ(Bytes(in), Bytes(out2));
|
||||
|
||||
// The "stateful" AEADs for implementing pre-AEAD cipher suites need to be
|
||||
// reset after each operation.
|
||||
ctx.Reset();
|
||||
ASSERT_TRUE(EVP_AEAD_CTX_init_with_direction(
|
||||
ctx.get(), aead(), key.data(), key.size(), tag_len, evp_aead_open));
|
||||
|
||||
// Garbage at the end isn't ignored.
|
||||
out.push_back(0);
|
||||
out2.resize(out.size());
|
||||
EXPECT_FALSE(EVP_AEAD_CTX_open(
|
||||
ctx.get(), out2.data(), &out2_len, out2.size(), nonce.data(),
|
||||
nonce.size(), out.data(), out.size(), ad.data(), ad.size()))
|
||||
<< "Decrypted bad data with trailing garbage.";
|
||||
ERR_clear_error();
|
||||
|
||||
// The "stateful" AEADs for implementing pre-AEAD cipher suites need to be
|
||||
// reset after each operation.
|
||||
ctx.Reset();
|
||||
ASSERT_TRUE(EVP_AEAD_CTX_init_with_direction(
|
||||
ctx.get(), aead(), key.data(), key.size(), tag_len, evp_aead_open));
|
||||
|
||||
// Verify integrity is checked.
|
||||
out[0] ^= 0x80;
|
||||
out.resize(out.size() - 1);
|
||||
out2.resize(out.size());
|
||||
EXPECT_FALSE(EVP_AEAD_CTX_open(
|
||||
ctx.get(), out2.data(), &out2_len, out2.size(), nonce.data(),
|
||||
nonce.size(), out.data(), out.size(), ad.data(), ad.size()))
|
||||
<< "Decrypted bad data with corrupted byte.";
|
||||
ERR_clear_error();
|
||||
});
|
||||
}
|
||||
|
||||
TEST_P(PerAEADTest, TestExtraInput) {
|
||||
const KnownAEAD &aead_config = GetParam();
|
||||
if (!aead()->seal_scatter_supports_extra_in) {
|
||||
return;
|
||||
}
|
||||
|
||||
const std::string test_vectors =
|
||||
"crypto/cipher_extra/test/" + std::string(aead_config.test_vectors);
|
||||
FileTestGTest(test_vectors.c_str(), [&](FileTest *t) {
|
||||
if (t->HasAttribute("NO_SEAL") ||
|
||||
t->HasAttribute("FAILS")) {
|
||||
t->SkipCurrent();
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<uint8_t> key, nonce, in, ad, ct, tag;
|
||||
ASSERT_TRUE(t->GetBytes(&key, "KEY"));
|
||||
ASSERT_TRUE(t->GetBytes(&nonce, "NONCE"));
|
||||
ASSERT_TRUE(t->GetBytes(&in, "IN"));
|
||||
ASSERT_TRUE(t->GetBytes(&ad, "AD"));
|
||||
ASSERT_TRUE(t->GetBytes(&ct, "CT"));
|
||||
ASSERT_TRUE(t->GetBytes(&tag, "TAG"));
|
||||
|
||||
bssl::ScopedEVP_AEAD_CTX ctx;
|
||||
ASSERT_TRUE(EVP_AEAD_CTX_init(ctx.get(), aead(), key.data(), key.size(),
|
||||
tag.size(), nullptr));
|
||||
std::vector<uint8_t> out_tag(EVP_AEAD_max_overhead(aead()) + in.size());
|
||||
std::vector<uint8_t> out(in.size());
|
||||
|
||||
for (size_t extra_in_size = 0; extra_in_size < in.size(); extra_in_size++) {
|
||||
size_t tag_bytes_written;
|
||||
SCOPED_TRACE(extra_in_size);
|
||||
ASSERT_TRUE(EVP_AEAD_CTX_seal_scatter(
|
||||
ctx.get(), out.data(), out_tag.data(), &tag_bytes_written,
|
||||
out_tag.size(), nonce.data(), nonce.size(), in.data(),
|
||||
in.size() - extra_in_size, in.data() + in.size() - extra_in_size,
|
||||
extra_in_size, ad.data(), ad.size()));
|
||||
|
||||
ASSERT_EQ(tag_bytes_written, extra_in_size + tag.size());
|
||||
|
||||
memcpy(out.data() + in.size() - extra_in_size, out_tag.data(),
|
||||
extra_in_size);
|
||||
|
||||
EXPECT_EQ(Bytes(ct), Bytes(out.data(), in.size()));
|
||||
EXPECT_EQ(Bytes(tag), Bytes(out_tag.data() + extra_in_size,
|
||||
tag_bytes_written - extra_in_size));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
TEST_P(PerAEADTest, TestVectorScatterGather) {
|
||||
std::string test_vectors = "crypto/cipher_extra/test/";
|
||||
const KnownAEAD &aead_config = GetParam();
|
||||
test_vectors += aead_config.test_vectors;
|
||||
FileTestGTest(test_vectors.c_str(), [&](FileTest *t) {
|
||||
std::vector<uint8_t> key, nonce, in, ad, ct, tag;
|
||||
ASSERT_TRUE(t->GetBytes(&key, "KEY"));
|
||||
ASSERT_TRUE(t->GetBytes(&nonce, "NONCE"));
|
||||
ASSERT_TRUE(t->GetBytes(&in, "IN"));
|
||||
ASSERT_TRUE(t->GetBytes(&ad, "AD"));
|
||||
ASSERT_TRUE(t->GetBytes(&ct, "CT"));
|
||||
ASSERT_TRUE(t->GetBytes(&tag, "TAG"));
|
||||
size_t tag_len = tag.size();
|
||||
if (t->HasAttribute("TAG_LEN")) {
|
||||
// Legacy AEADs are MAC-then-encrypt and may include padding in the TAG
|
||||
// field. TAG_LEN contains the actual size of the digest in that case.
|
||||
std::string tag_len_str;
|
||||
ASSERT_TRUE(t->GetAttribute(&tag_len_str, "TAG_LEN"));
|
||||
tag_len = strtoul(tag_len_str.c_str(), nullptr, 10);
|
||||
ASSERT_TRUE(tag_len);
|
||||
}
|
||||
|
||||
bssl::ScopedEVP_AEAD_CTX ctx;
|
||||
ASSERT_TRUE(EVP_AEAD_CTX_init_with_direction(
|
||||
ctx.get(), aead(), key.data(), key.size(), tag_len, evp_aead_seal));
|
||||
|
||||
std::vector<uint8_t> out(in.size());
|
||||
std::vector<uint8_t> out_tag(EVP_AEAD_max_overhead(aead()));
|
||||
if (!t->HasAttribute("NO_SEAL")) {
|
||||
size_t out_tag_len;
|
||||
ASSERT_TRUE(EVP_AEAD_CTX_seal_scatter(
|
||||
ctx.get(), out.data(), out_tag.data(), &out_tag_len, out_tag.size(),
|
||||
nonce.data(), nonce.size(), in.data(), in.size(), nullptr, 0,
|
||||
ad.data(), ad.size()));
|
||||
out_tag.resize(out_tag_len);
|
||||
|
||||
ASSERT_EQ(out.size(), ct.size());
|
||||
ASSERT_EQ(out_tag.size(), tag.size());
|
||||
EXPECT_EQ(Bytes(ct), Bytes(out.data(), ct.size()));
|
||||
EXPECT_EQ(Bytes(tag), Bytes(out_tag.data(), tag.size()));
|
||||
} else {
|
||||
out.resize(ct.size());
|
||||
out_tag.resize(tag.size());
|
||||
OPENSSL_memcpy(out.data(), ct.data(), ct.size());
|
||||
OPENSSL_memcpy(out_tag.data(), tag.data(), tag.size());
|
||||
}
|
||||
|
||||
// The "stateful" AEADs for implementing pre-AEAD cipher suites need to be
|
||||
// reset after each operation.
|
||||
ctx.Reset();
|
||||
ASSERT_TRUE(EVP_AEAD_CTX_init_with_direction(
|
||||
ctx.get(), aead(), key.data(), key.size(), tag_len, evp_aead_open));
|
||||
|
||||
std::vector<uint8_t> out2(out.size());
|
||||
int ret = EVP_AEAD_CTX_open_gather(
|
||||
ctx.get(), out2.data(), nonce.data(), nonce.size(), out.data(),
|
||||
out.size(), out_tag.data(), out_tag.size(), ad.data(), ad.size());
|
||||
|
||||
// Skip decryption for AEADs that don't implement open_gather().
|
||||
if (!ret) {
|
||||
int err = ERR_peek_error();
|
||||
if (ERR_GET_LIB(err) == ERR_LIB_CIPHER &&
|
||||
ERR_GET_REASON(err) == CIPHER_R_CTRL_NOT_IMPLEMENTED) {
|
||||
t->SkipCurrent();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (t->HasAttribute("FAILS")) {
|
||||
ASSERT_FALSE(ret) << "Decrypted bad data";
|
||||
ERR_clear_error();
|
||||
return;
|
||||
}
|
||||
|
||||
ASSERT_TRUE(ret) << "Failed to decrypt: "
|
||||
<< ERR_reason_error_string(ERR_get_error());
|
||||
EXPECT_EQ(Bytes(in), Bytes(out2));
|
||||
|
||||
// The "stateful" AEADs for implementing pre-AEAD cipher suites need to be
|
||||
// reset after each operation.
|
||||
ctx.Reset();
|
||||
ASSERT_TRUE(EVP_AEAD_CTX_init_with_direction(
|
||||
ctx.get(), aead(), key.data(), key.size(), tag_len, evp_aead_open));
|
||||
|
||||
// Garbage at the end isn't ignored.
|
||||
out_tag.push_back(0);
|
||||
out2.resize(out.size());
|
||||
EXPECT_FALSE(EVP_AEAD_CTX_open_gather(
|
||||
ctx.get(), out2.data(), nonce.data(), nonce.size(), out.data(),
|
||||
out.size(), out_tag.data(), out_tag.size(), ad.data(), ad.size()))
|
||||
<< "Decrypted bad data with trailing garbage.";
|
||||
ERR_clear_error();
|
||||
|
||||
// The "stateful" AEADs for implementing pre-AEAD cipher suites need to be
|
||||
// reset after each operation.
|
||||
ctx.Reset();
|
||||
ASSERT_TRUE(EVP_AEAD_CTX_init_with_direction(
|
||||
ctx.get(), aead(), key.data(), key.size(), tag_len, evp_aead_open));
|
||||
|
||||
// Verify integrity is checked.
|
||||
out_tag[0] ^= 0x80;
|
||||
out_tag.resize(out_tag.size() - 1);
|
||||
out2.resize(out.size());
|
||||
EXPECT_FALSE(EVP_AEAD_CTX_open_gather(
|
||||
ctx.get(), out2.data(), nonce.data(), nonce.size(), out.data(),
|
||||
out.size(), out_tag.data(), out_tag.size(), ad.data(), ad.size()))
|
||||
<< "Decrypted bad data with corrupted byte.";
|
||||
ERR_clear_error();
|
||||
|
||||
ctx.Reset();
|
||||
ASSERT_TRUE(EVP_AEAD_CTX_init_with_direction(
|
||||
ctx.get(), aead(), key.data(), key.size(), tag_len, evp_aead_open));
|
||||
|
||||
// Check edge case for tag length.
|
||||
EXPECT_FALSE(EVP_AEAD_CTX_open_gather(
|
||||
ctx.get(), out2.data(), nonce.data(), nonce.size(), out.data(),
|
||||
out.size(), out_tag.data(), 0, ad.data(), ad.size()))
|
||||
<< "Decrypted bad data with corrupted byte.";
|
||||
ERR_clear_error();
|
||||
});
|
||||
}
|
||||
|
||||
TEST_P(PerAEADTest, CleanupAfterInitFailure) {
|
||||
uint8_t key[EVP_AEAD_MAX_KEY_LENGTH];
|
||||
OPENSSL_memset(key, 0, sizeof(key));
|
||||
const size_t key_len = EVP_AEAD_key_length(aead());
|
||||
ASSERT_GE(sizeof(key), key_len);
|
||||
|
||||
EVP_AEAD_CTX ctx;
|
||||
ASSERT_FALSE(EVP_AEAD_CTX_init(
|
||||
&ctx, aead(), key, key_len,
|
||||
9999 /* a silly tag length to trigger an error */, NULL /* ENGINE */));
|
||||
ERR_clear_error();
|
||||
|
||||
// Running a second, failed _init should not cause a memory leak.
|
||||
ASSERT_FALSE(EVP_AEAD_CTX_init(
|
||||
&ctx, aead(), key, key_len,
|
||||
9999 /* a silly tag length to trigger an error */, NULL /* ENGINE */));
|
||||
ERR_clear_error();
|
||||
|
||||
// Calling _cleanup on an |EVP_AEAD_CTX| after a failed _init should be a
|
||||
// no-op.
|
||||
EVP_AEAD_CTX_cleanup(&ctx);
|
||||
}
|
||||
|
||||
TEST_P(PerAEADTest, TruncatedTags) {
|
||||
if (!GetParam().truncated_tags) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t key[EVP_AEAD_MAX_KEY_LENGTH];
|
||||
OPENSSL_memset(key, 0, sizeof(key));
|
||||
const size_t key_len = EVP_AEAD_key_length(aead());
|
||||
ASSERT_GE(sizeof(key), key_len);
|
||||
|
||||
uint8_t nonce[EVP_AEAD_MAX_NONCE_LENGTH];
|
||||
OPENSSL_memset(nonce, 0, sizeof(nonce));
|
||||
const size_t nonce_len = EVP_AEAD_nonce_length(aead());
|
||||
ASSERT_GE(sizeof(nonce), nonce_len);
|
||||
|
||||
bssl::ScopedEVP_AEAD_CTX ctx;
|
||||
ASSERT_TRUE(EVP_AEAD_CTX_init(ctx.get(), aead(), key, key_len,
|
||||
1 /* one byte tag */, NULL /* ENGINE */));
|
||||
|
||||
const uint8_t plaintext[1] = {'A'};
|
||||
|
||||
uint8_t ciphertext[128];
|
||||
size_t ciphertext_len;
|
||||
constexpr uint8_t kSentinel = 42;
|
||||
OPENSSL_memset(ciphertext, kSentinel, sizeof(ciphertext));
|
||||
|
||||
ASSERT_TRUE(EVP_AEAD_CTX_seal(ctx.get(), ciphertext, &ciphertext_len,
|
||||
sizeof(ciphertext), nonce, nonce_len, plaintext,
|
||||
sizeof(plaintext), nullptr /* ad */, 0));
|
||||
|
||||
for (size_t i = ciphertext_len; i < sizeof(ciphertext); i++) {
|
||||
// Sealing must not write past where it said it did.
|
||||
EXPECT_EQ(kSentinel, ciphertext[i])
|
||||
<< "Sealing wrote off the end of the buffer.";
|
||||
}
|
||||
|
||||
const size_t overhead_used = ciphertext_len - sizeof(plaintext);
|
||||
const size_t expected_overhead =
|
||||
1 + EVP_AEAD_max_overhead(aead()) - EVP_AEAD_max_tag_len(aead());
|
||||
EXPECT_EQ(overhead_used, expected_overhead)
|
||||
<< "AEAD is probably ignoring request to truncate tags.";
|
||||
|
||||
uint8_t plaintext2[sizeof(plaintext) + 16];
|
||||
OPENSSL_memset(plaintext2, kSentinel, sizeof(plaintext2));
|
||||
|
||||
size_t plaintext2_len;
|
||||
ASSERT_TRUE(EVP_AEAD_CTX_open(
|
||||
ctx.get(), plaintext2, &plaintext2_len, sizeof(plaintext2), nonce,
|
||||
nonce_len, ciphertext, ciphertext_len, nullptr /* ad */, 0))
|
||||
<< "Opening with truncated tag didn't work.";
|
||||
|
||||
for (size_t i = plaintext2_len; i < sizeof(plaintext2); i++) {
|
||||
// Likewise, opening should also stay within bounds.
|
||||
EXPECT_EQ(kSentinel, plaintext2[i])
|
||||
<< "Opening wrote off the end of the buffer.";
|
||||
}
|
||||
|
||||
EXPECT_EQ(Bytes(plaintext), Bytes(plaintext2, plaintext2_len));
|
||||
}
|
||||
|
||||
TEST_P(PerAEADTest, AliasedBuffers) {
|
||||
if (GetParam().limited_implementation) {
|
||||
return;
|
||||
}
|
||||
|
||||
const size_t key_len = EVP_AEAD_key_length(aead());
|
||||
const size_t nonce_len = EVP_AEAD_nonce_length(aead());
|
||||
const size_t max_overhead = EVP_AEAD_max_overhead(aead());
|
||||
|
||||
std::vector<uint8_t> key(key_len, 'a');
|
||||
bssl::ScopedEVP_AEAD_CTX ctx;
|
||||
ASSERT_TRUE(EVP_AEAD_CTX_init(ctx.get(), aead(), key.data(), key_len,
|
||||
EVP_AEAD_DEFAULT_TAG_LENGTH, nullptr));
|
||||
|
||||
static const uint8_t kPlaintext[260] =
|
||||
"testing123456testing123456testing123456testing123456testing123456testing"
|
||||
"123456testing123456testing123456testing123456testing123456testing123456t"
|
||||
"esting123456testing123456testing123456testing123456testing123456testing1"
|
||||
"23456testing123456testing123456testing12345";
|
||||
const std::vector<size_t> offsets = {
|
||||
0, 1, 2, 8, 15, 16, 17, 31, 32, 33, 63,
|
||||
64, 65, 95, 96, 97, 127, 128, 129, 255, 256, 257,
|
||||
};
|
||||
|
||||
std::vector<uint8_t> nonce(nonce_len, 'b');
|
||||
std::vector<uint8_t> valid_encryption(sizeof(kPlaintext) + max_overhead);
|
||||
size_t valid_encryption_len;
|
||||
ASSERT_TRUE(EVP_AEAD_CTX_seal(
|
||||
ctx.get(), valid_encryption.data(), &valid_encryption_len,
|
||||
sizeof(kPlaintext) + max_overhead, nonce.data(), nonce_len, kPlaintext,
|
||||
sizeof(kPlaintext), nullptr, 0))
|
||||
<< "EVP_AEAD_CTX_seal failed with disjoint buffers.";
|
||||
|
||||
// Test with out != in which we expect to fail.
|
||||
std::vector<uint8_t> buffer(2 + valid_encryption_len);
|
||||
uint8_t *in = buffer.data() + 1;
|
||||
uint8_t *out1 = buffer.data();
|
||||
uint8_t *out2 = buffer.data() + 2;
|
||||
|
||||
OPENSSL_memcpy(in, kPlaintext, sizeof(kPlaintext));
|
||||
size_t out_len;
|
||||
EXPECT_FALSE(EVP_AEAD_CTX_seal(
|
||||
ctx.get(), out1 /* in - 1 */, &out_len, sizeof(kPlaintext) + max_overhead,
|
||||
nonce.data(), nonce_len, in, sizeof(kPlaintext), nullptr, 0));
|
||||
EXPECT_FALSE(EVP_AEAD_CTX_seal(
|
||||
ctx.get(), out2 /* in + 1 */, &out_len, sizeof(kPlaintext) + max_overhead,
|
||||
nonce.data(), nonce_len, in, sizeof(kPlaintext), nullptr, 0));
|
||||
ERR_clear_error();
|
||||
|
||||
OPENSSL_memcpy(in, valid_encryption.data(), valid_encryption_len);
|
||||
EXPECT_FALSE(EVP_AEAD_CTX_open(ctx.get(), out1 /* in - 1 */, &out_len,
|
||||
valid_encryption_len, nonce.data(), nonce_len,
|
||||
in, valid_encryption_len, nullptr, 0));
|
||||
EXPECT_FALSE(EVP_AEAD_CTX_open(ctx.get(), out2 /* in + 1 */, &out_len,
|
||||
valid_encryption_len, nonce.data(), nonce_len,
|
||||
in, valid_encryption_len, nullptr, 0));
|
||||
ERR_clear_error();
|
||||
|
||||
// Test with out == in, which we expect to work.
|
||||
OPENSSL_memcpy(in, kPlaintext, sizeof(kPlaintext));
|
||||
|
||||
ASSERT_TRUE(EVP_AEAD_CTX_seal(ctx.get(), in, &out_len,
|
||||
sizeof(kPlaintext) + max_overhead, nonce.data(),
|
||||
nonce_len, in, sizeof(kPlaintext), nullptr, 0));
|
||||
EXPECT_EQ(Bytes(valid_encryption.data(), valid_encryption_len),
|
||||
Bytes(in, out_len));
|
||||
|
||||
OPENSSL_memcpy(in, valid_encryption.data(), valid_encryption_len);
|
||||
ASSERT_TRUE(EVP_AEAD_CTX_open(ctx.get(), in, &out_len, valid_encryption_len,
|
||||
nonce.data(), nonce_len, in,
|
||||
valid_encryption_len, nullptr, 0));
|
||||
EXPECT_EQ(Bytes(kPlaintext), Bytes(in, out_len));
|
||||
}
|
||||
|
||||
TEST_P(PerAEADTest, UnalignedInput) {
|
||||
alignas(64) uint8_t key[EVP_AEAD_MAX_KEY_LENGTH + 1];
|
||||
alignas(64) uint8_t nonce[EVP_AEAD_MAX_NONCE_LENGTH + 1];
|
||||
alignas(64) uint8_t plaintext[32 + 1];
|
||||
alignas(64) uint8_t ad[32 + 1];
|
||||
OPENSSL_memset(key, 'K', sizeof(key));
|
||||
OPENSSL_memset(nonce, 'N', sizeof(nonce));
|
||||
OPENSSL_memset(plaintext, 'P', sizeof(plaintext));
|
||||
OPENSSL_memset(ad, 'A', sizeof(ad));
|
||||
const size_t key_len = EVP_AEAD_key_length(aead());
|
||||
ASSERT_GE(sizeof(key) - 1, key_len);
|
||||
const size_t nonce_len = EVP_AEAD_nonce_length(aead());
|
||||
ASSERT_GE(sizeof(nonce) - 1, nonce_len);
|
||||
const size_t ad_len =
|
||||
GetParam().ad_len != 0 ? GetParam().ad_len : sizeof(ad) - 1;
|
||||
ASSERT_GE(sizeof(ad) - 1, ad_len);
|
||||
|
||||
// Encrypt some input.
|
||||
bssl::ScopedEVP_AEAD_CTX ctx;
|
||||
ASSERT_TRUE(EVP_AEAD_CTX_init_with_direction(
|
||||
ctx.get(), aead(), key + 1, key_len, EVP_AEAD_DEFAULT_TAG_LENGTH,
|
||||
evp_aead_seal));
|
||||
alignas(64) uint8_t ciphertext[sizeof(plaintext) + EVP_AEAD_MAX_OVERHEAD];
|
||||
size_t ciphertext_len;
|
||||
ASSERT_TRUE(EVP_AEAD_CTX_seal(ctx.get(), ciphertext + 1, &ciphertext_len,
|
||||
sizeof(ciphertext) - 1, nonce + 1, nonce_len,
|
||||
plaintext + 1, sizeof(plaintext) - 1, ad + 1,
|
||||
ad_len));
|
||||
|
||||
// It must successfully decrypt.
|
||||
alignas(64) uint8_t out[sizeof(ciphertext)];
|
||||
ctx.Reset();
|
||||
ASSERT_TRUE(EVP_AEAD_CTX_init_with_direction(
|
||||
ctx.get(), aead(), key + 1, key_len, EVP_AEAD_DEFAULT_TAG_LENGTH,
|
||||
evp_aead_open));
|
||||
size_t out_len;
|
||||
ASSERT_TRUE(EVP_AEAD_CTX_open(ctx.get(), out + 1, &out_len, sizeof(out) - 1,
|
||||
nonce + 1, nonce_len, ciphertext + 1,
|
||||
ciphertext_len, ad + 1, ad_len));
|
||||
EXPECT_EQ(Bytes(plaintext + 1, sizeof(plaintext) - 1),
|
||||
Bytes(out + 1, out_len));
|
||||
}
|
||||
|
||||
TEST_P(PerAEADTest, Overflow) {
|
||||
alignas(64) uint8_t key[EVP_AEAD_MAX_KEY_LENGTH];
|
||||
OPENSSL_memset(key, 'K', sizeof(key));
|
||||
|
||||
bssl::ScopedEVP_AEAD_CTX ctx;
|
||||
const size_t max_tag_len = EVP_AEAD_max_tag_len(aead());
|
||||
ASSERT_TRUE(EVP_AEAD_CTX_init_with_direction(ctx.get(), aead(), key,
|
||||
EVP_AEAD_key_length(aead()),
|
||||
max_tag_len, evp_aead_seal));
|
||||
|
||||
uint8_t plaintext[1] = {0};
|
||||
uint8_t ciphertext[1024] = {0};
|
||||
size_t ciphertext_len;
|
||||
// The AEAD must not overflow when calculating the ciphertext length.
|
||||
ASSERT_FALSE(EVP_AEAD_CTX_seal(
|
||||
ctx.get(), ciphertext, &ciphertext_len, sizeof(ciphertext), nullptr, 0,
|
||||
plaintext, std::numeric_limits<size_t>::max() - max_tag_len + 1, nullptr,
|
||||
0));
|
||||
ERR_clear_error();
|
||||
|
||||
// (Can't test the scatter interface because it'll attempt to zero the output
|
||||
// buffer on error and the primary output buffer is implicitly the same size
|
||||
// as the input.)
|
||||
}
|
||||
|
||||
// Test that EVP_aead_aes_128_gcm and EVP_aead_aes_256_gcm reject empty nonces.
|
||||
// AES-GCM is not defined for those.
|
||||
TEST(AEADTest, AESGCMEmptyNonce) {
|
||||
static const uint8_t kZeros[32] = {0};
|
||||
|
||||
// Test AES-128-GCM.
|
||||
uint8_t buf[16];
|
||||
size_t len;
|
||||
bssl::ScopedEVP_AEAD_CTX ctx;
|
||||
ASSERT_TRUE(EVP_AEAD_CTX_init(ctx.get(), EVP_aead_aes_128_gcm(), kZeros, 16,
|
||||
EVP_AEAD_DEFAULT_TAG_LENGTH, nullptr));
|
||||
|
||||
EXPECT_FALSE(EVP_AEAD_CTX_seal(ctx.get(), buf, &len, sizeof(buf),
|
||||
nullptr /* nonce */, 0, nullptr /* in */, 0,
|
||||
nullptr /* ad */, 0));
|
||||
uint32_t err = ERR_get_error();
|
||||
EXPECT_EQ(ERR_LIB_CIPHER, ERR_GET_LIB(err));
|
||||
EXPECT_EQ(CIPHER_R_INVALID_NONCE_SIZE, ERR_GET_REASON(err));
|
||||
|
||||
EXPECT_FALSE(EVP_AEAD_CTX_open(ctx.get(), buf, &len, sizeof(buf),
|
||||
nullptr /* nonce */, 0, kZeros /* in */,
|
||||
sizeof(kZeros), nullptr /* ad */, 0));
|
||||
err = ERR_get_error();
|
||||
EXPECT_EQ(ERR_LIB_CIPHER, ERR_GET_LIB(err));
|
||||
EXPECT_EQ(CIPHER_R_INVALID_NONCE_SIZE, ERR_GET_REASON(err));
|
||||
|
||||
// Test AES-256-GCM.
|
||||
ctx.Reset();
|
||||
ASSERT_TRUE(EVP_AEAD_CTX_init(ctx.get(), EVP_aead_aes_256_gcm(), kZeros, 32,
|
||||
EVP_AEAD_DEFAULT_TAG_LENGTH, nullptr));
|
||||
|
||||
EXPECT_FALSE(EVP_AEAD_CTX_seal(ctx.get(), buf, &len, sizeof(buf),
|
||||
nullptr /* nonce */, 0, nullptr /* in */, 0,
|
||||
nullptr /* ad */, 0));
|
||||
err = ERR_get_error();
|
||||
EXPECT_EQ(ERR_LIB_CIPHER, ERR_GET_LIB(err));
|
||||
EXPECT_EQ(CIPHER_R_INVALID_NONCE_SIZE, ERR_GET_REASON(err));
|
||||
|
||||
EXPECT_FALSE(EVP_AEAD_CTX_open(ctx.get(), buf, &len, sizeof(buf),
|
||||
nullptr /* nonce */, 0, kZeros /* in */,
|
||||
sizeof(kZeros), nullptr /* ad */, 0));
|
||||
err = ERR_get_error();
|
||||
EXPECT_EQ(ERR_LIB_CIPHER, ERR_GET_LIB(err));
|
||||
EXPECT_EQ(CIPHER_R_INVALID_NONCE_SIZE, ERR_GET_REASON(err));
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
+115
-7
@@ -78,6 +78,7 @@ chacha20_poly1305_constants:
|
||||
.byte 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,0x00
|
||||
.byte 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00
|
||||
.byte 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00
|
||||
.byte 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
|
||||
___
|
||||
|
||||
my ($oup,$inp,$inl,$adp,$keyp,$itr1,$itr2)=("%rdi","%rsi","%rbx","%rcx","%r9","%rcx","%r8");
|
||||
@@ -856,7 +857,9 @@ chacha20_poly1305_seal:
|
||||
.cfi_offset r15, -56
|
||||
lea 32(%rsp), %rbp
|
||||
and \$-32, %rbp
|
||||
mov %rdx, 8+$len_store
|
||||
mov 56($keyp), $inl # extra_in_len
|
||||
addq %rdx, $inl
|
||||
mov $inl, 8+$len_store
|
||||
mov %r8, 0+$len_store
|
||||
mov %rdx, $inl\n"; $code.="
|
||||
mov OPENSSL_ia32cap_P+8(%rip), %eax
|
||||
@@ -1093,11 +1096,9 @@ seal_sse_128_seal:
|
||||
|
||||
seal_sse_tail_16:
|
||||
test $inl, $inl
|
||||
jz seal_sse_finalize
|
||||
jz process_blocks_of_extra_in
|
||||
# We can only load the PT one byte at a time to avoid buffer overread
|
||||
mov $inl, $itr2
|
||||
shl \$4, $itr2
|
||||
lea .and_masks(%rip), $t0
|
||||
mov $inl, $itr1
|
||||
lea -1($inp, $inl), $inp
|
||||
pxor $T3, $T3
|
||||
@@ -1106,7 +1107,7 @@ seal_sse_tail_16:
|
||||
pinsrb \$0, ($inp), $T3
|
||||
lea -1($inp), $inp
|
||||
dec $itr1
|
||||
jne 1b
|
||||
jne 1b
|
||||
|
||||
# XOR the keystream with the plaintext.
|
||||
pxor $A0, $T3
|
||||
@@ -1121,14 +1122,121 @@ seal_sse_tail_16:
|
||||
sub \$1, $itr1
|
||||
jnz 2b
|
||||
|
||||
pand -16($t0, $itr2), $T3
|
||||
# $T3 contains the final (partial, non-empty) block of ciphertext which
|
||||
# needs to be fed into the Poly1305 state. The right-most $inl bytes of it
|
||||
# are valid. We need to fill it with extra_in bytes until full, or until we
|
||||
# run out of bytes.
|
||||
#
|
||||
# $keyp points to the tag output, which is actually a struct with the
|
||||
# extra_in pointer and length at offset 48.
|
||||
movq 288+32(%rsp), $keyp
|
||||
movq 56($keyp), $t1 # extra_in_len
|
||||
movq 48($keyp), $t0 # extra_in
|
||||
test $t1, $t1
|
||||
jz process_partial_block # Common case: no bytes of extra_in
|
||||
|
||||
movq \$16, $t2
|
||||
subq $inl, $t2 # 16-$inl is the number of bytes that fit into $T3.
|
||||
cmpq $t2, $t1 # if extra_in_len < 16-$inl, only copy extra_in_len
|
||||
# (note that AT&T syntax reverses the arguments)
|
||||
jge load_extra_in
|
||||
movq $t1, $t2
|
||||
|
||||
load_extra_in:
|
||||
# $t2 contains the number of bytes of extra_in (pointed to by $t0) to load
|
||||
# into $T3. They are loaded in reverse order.
|
||||
leaq -1($t0, $t2), $inp
|
||||
# Update extra_in and extra_in_len to reflect the bytes that are about to
|
||||
# be read.
|
||||
addq $t2, $t0
|
||||
subq $t2, $t1
|
||||
movq $t0, 48($keyp)
|
||||
movq $t1, 56($keyp)
|
||||
|
||||
# Update $itr2, which is used to select the mask later on, to reflect the
|
||||
# extra bytes about to be added.
|
||||
addq $t2, $itr2
|
||||
|
||||
# Load $t2 bytes of extra_in into $T2.
|
||||
pxor $T2, $T2
|
||||
3:
|
||||
pslldq \$1, $T2
|
||||
pinsrb \$0, ($inp), $T2
|
||||
lea -1($inp), $inp
|
||||
sub \$1, $t2
|
||||
jnz 3b
|
||||
|
||||
# Shift $T2 up the length of the remainder from the main encryption. Sadly,
|
||||
# the shift for an XMM register has to be a constant, thus we loop to do
|
||||
# this.
|
||||
movq $inl, $t2
|
||||
|
||||
4:
|
||||
pslldq \$1, $T2
|
||||
sub \$1, $t2
|
||||
jnz 4b
|
||||
|
||||
# Mask $T3 (the remainder from the main encryption) so that superfluous
|
||||
# bytes are zero. This means that the non-zero bytes in $T2 and $T3 are
|
||||
# disjoint and so we can merge them with an OR.
|
||||
lea .and_masks(%rip), $t2
|
||||
shl \$4, $inl
|
||||
pand -16($t2, $inl), $T3
|
||||
|
||||
# Merge $T2 into $T3, forming the remainder block.
|
||||
por $T2, $T3
|
||||
|
||||
# The block of ciphertext + extra_in is ready to be included in the
|
||||
# Poly1305 state.
|
||||
movq $T3, $t0
|
||||
pextrq \$1, $T3, $t1
|
||||
add $t0, $acc0
|
||||
adc $t1, $acc1
|
||||
adc \$1, $acc2\n";
|
||||
&poly_mul(); $code.="
|
||||
seal_sse_finalize:\n";
|
||||
|
||||
process_blocks_of_extra_in:
|
||||
# There may be additional bytes of extra_in to process.
|
||||
movq 288+32(%rsp), $keyp
|
||||
movq 48($keyp), $inp # extra_in
|
||||
movq 56($keyp), $itr2 # extra_in_len
|
||||
movq $itr2, $itr1
|
||||
shr \$4, $itr2 # number of blocks
|
||||
|
||||
5:
|
||||
jz process_extra_in_trailer\n";
|
||||
&poly_add("0($inp)");
|
||||
&poly_mul(); $code.="
|
||||
leaq 16($inp), $inp
|
||||
subq \$1, $itr2
|
||||
jmp 5b
|
||||
|
||||
process_extra_in_trailer:
|
||||
andq \$15, $itr1 # remaining num bytes (<16) of extra_in
|
||||
movq $itr1, $inl
|
||||
jz do_length_block
|
||||
leaq -1($inp, $itr1), $inp
|
||||
|
||||
6:
|
||||
pslldq \$1, $T3
|
||||
pinsrb \$0, ($inp), $T3
|
||||
lea -1($inp), $inp
|
||||
sub \$1, $itr1
|
||||
jnz 6b
|
||||
|
||||
process_partial_block:
|
||||
# $T3 contains $inl bytes of data to be fed into Poly1305. $inl != 0
|
||||
lea .and_masks(%rip), $t2
|
||||
shl \$4, $inl
|
||||
pand -16($t2, $inl), $T3
|
||||
movq $T3, $t0
|
||||
pextrq \$1, $T3, $t1
|
||||
add $t0, $acc0
|
||||
adc $t1, $acc1
|
||||
adc \$1, $acc2\n";
|
||||
&poly_mul(); $code.="
|
||||
|
||||
do_length_block:\n";
|
||||
&poly_add($len_store);
|
||||
&poly_mul(); $code.="
|
||||
# Final reduce
|
||||
@@ -0,0 +1,114 @@
|
||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young (eay@cryptsoft.com).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young (eay@cryptsoft.com)"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.] */
|
||||
|
||||
#include <openssl/cipher.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.h>
|
||||
#include <openssl/nid.h>
|
||||
|
||||
#include "internal.h"
|
||||
#include "../internal.h"
|
||||
|
||||
|
||||
const EVP_CIPHER *EVP_get_cipherbynid(int nid) {
|
||||
switch (nid) {
|
||||
case NID_rc2_cbc:
|
||||
return EVP_rc2_cbc();
|
||||
case NID_rc2_40_cbc:
|
||||
return EVP_rc2_40_cbc();
|
||||
case NID_des_ede3_cbc:
|
||||
return EVP_des_ede3_cbc();
|
||||
case NID_des_ede_cbc:
|
||||
return EVP_des_cbc();
|
||||
case NID_aes_128_cbc:
|
||||
return EVP_aes_128_cbc();
|
||||
case NID_aes_192_cbc:
|
||||
return EVP_aes_192_cbc();
|
||||
case NID_aes_256_cbc:
|
||||
return EVP_aes_256_cbc();
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
const EVP_CIPHER *EVP_get_cipherbyname(const char *name) {
|
||||
if (OPENSSL_strcasecmp(name, "rc4") == 0) {
|
||||
return EVP_rc4();
|
||||
} else if (OPENSSL_strcasecmp(name, "des-cbc") == 0) {
|
||||
return EVP_des_cbc();
|
||||
} else if (OPENSSL_strcasecmp(name, "des-ede3-cbc") == 0 ||
|
||||
OPENSSL_strcasecmp(name, "3des") == 0) {
|
||||
return EVP_des_ede3_cbc();
|
||||
} else if (OPENSSL_strcasecmp(name, "aes-128-cbc") == 0) {
|
||||
return EVP_aes_128_cbc();
|
||||
} else if (OPENSSL_strcasecmp(name, "aes-256-cbc") == 0) {
|
||||
return EVP_aes_256_cbc();
|
||||
} else if (OPENSSL_strcasecmp(name, "aes-128-ctr") == 0) {
|
||||
return EVP_aes_128_ctr();
|
||||
} else if (OPENSSL_strcasecmp(name, "aes-256-ctr") == 0) {
|
||||
return EVP_aes_256_ctr();
|
||||
} else if (OPENSSL_strcasecmp(name, "aes-128-ecb") == 0) {
|
||||
return EVP_aes_128_ecb();
|
||||
} else if (OPENSSL_strcasecmp(name, "aes-256-ecb") == 0) {
|
||||
return EVP_aes_256_ecb();
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -0,0 +1,287 @@
|
||||
/*
|
||||
* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
|
||||
* project.
|
||||
*/
|
||||
/* ====================================================================
|
||||
* Copyright (c) 2015 The OpenSSL Project. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. All advertising materials mentioning features or use of this
|
||||
* software must display the following acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
|
||||
*
|
||||
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
|
||||
* endorse or promote products derived from this software without
|
||||
* prior written permission. For written permission, please contact
|
||||
* licensing@OpenSSL.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "OpenSSL"
|
||||
* nor may "OpenSSL" appear in their names without prior written
|
||||
* permission of the OpenSSL Project.
|
||||
*
|
||||
* 6. Redistributions of any form whatsoever must retain the following
|
||||
* acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
|
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <openssl/cipher.h>
|
||||
#include <openssl/err.h>
|
||||
|
||||
#include "../test/file_test.h"
|
||||
#include "../test/test_util.h"
|
||||
|
||||
|
||||
static const EVP_CIPHER *GetCipher(const std::string &name) {
|
||||
if (name == "DES-CBC") {
|
||||
return EVP_des_cbc();
|
||||
} else if (name == "DES-ECB") {
|
||||
return EVP_des_ecb();
|
||||
} else if (name == "DES-EDE") {
|
||||
return EVP_des_ede();
|
||||
} else if (name == "DES-EDE3") {
|
||||
return EVP_des_ede3();
|
||||
} else if (name == "DES-EDE-CBC") {
|
||||
return EVP_des_ede_cbc();
|
||||
} else if (name == "DES-EDE3-CBC") {
|
||||
return EVP_des_ede3_cbc();
|
||||
} else if (name == "RC4") {
|
||||
return EVP_rc4();
|
||||
} else if (name == "AES-128-ECB") {
|
||||
return EVP_aes_128_ecb();
|
||||
} else if (name == "AES-256-ECB") {
|
||||
return EVP_aes_256_ecb();
|
||||
} else if (name == "AES-128-CBC") {
|
||||
return EVP_aes_128_cbc();
|
||||
} else if (name == "AES-128-GCM") {
|
||||
return EVP_aes_128_gcm();
|
||||
} else if (name == "AES-128-OFB") {
|
||||
return EVP_aes_128_ofb();
|
||||
} else if (name == "AES-192-CBC") {
|
||||
return EVP_aes_192_cbc();
|
||||
} else if (name == "AES-192-CTR") {
|
||||
return EVP_aes_192_ctr();
|
||||
} else if (name == "AES-192-ECB") {
|
||||
return EVP_aes_192_ecb();
|
||||
} else if (name == "AES-256-CBC") {
|
||||
return EVP_aes_256_cbc();
|
||||
} else if (name == "AES-128-CTR") {
|
||||
return EVP_aes_128_ctr();
|
||||
} else if (name == "AES-256-CTR") {
|
||||
return EVP_aes_256_ctr();
|
||||
} else if (name == "AES-256-GCM") {
|
||||
return EVP_aes_256_gcm();
|
||||
} else if (name == "AES-256-OFB") {
|
||||
return EVP_aes_256_ofb();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static void TestOperation(FileTest *t, const EVP_CIPHER *cipher, bool encrypt,
|
||||
size_t chunk_size, const std::vector<uint8_t> &key,
|
||||
const std::vector<uint8_t> &iv,
|
||||
const std::vector<uint8_t> &plaintext,
|
||||
const std::vector<uint8_t> &ciphertext,
|
||||
const std::vector<uint8_t> &aad,
|
||||
const std::vector<uint8_t> &tag) {
|
||||
const std::vector<uint8_t> *in, *out;
|
||||
if (encrypt) {
|
||||
in = &plaintext;
|
||||
out = &ciphertext;
|
||||
} else {
|
||||
in = &ciphertext;
|
||||
out = &plaintext;
|
||||
}
|
||||
|
||||
bool is_aead = EVP_CIPHER_mode(cipher) == EVP_CIPH_GCM_MODE;
|
||||
|
||||
bssl::ScopedEVP_CIPHER_CTX ctx;
|
||||
ASSERT_TRUE(EVP_CipherInit_ex(ctx.get(), cipher, nullptr, nullptr, nullptr,
|
||||
encrypt ? 1 : 0));
|
||||
if (t->HasAttribute("IV")) {
|
||||
if (is_aead) {
|
||||
ASSERT_TRUE(
|
||||
EVP_CIPHER_CTX_ctrl(ctx.get(), EVP_CTRL_GCM_SET_IVLEN, iv.size(), 0));
|
||||
} else {
|
||||
ASSERT_EQ(iv.size(), EVP_CIPHER_CTX_iv_length(ctx.get()));
|
||||
}
|
||||
}
|
||||
if (is_aead && !encrypt) {
|
||||
ASSERT_TRUE(EVP_CIPHER_CTX_ctrl(ctx.get(), EVP_CTRL_GCM_SET_TAG, tag.size(),
|
||||
const_cast<uint8_t *>(tag.data())));
|
||||
}
|
||||
// The ciphers are run with no padding. For each of the ciphers we test, the
|
||||
// output size matches the input size.
|
||||
std::vector<uint8_t> result(in->size());
|
||||
ASSERT_EQ(in->size(), out->size());
|
||||
int unused, result_len1 = 0, result_len2;
|
||||
ASSERT_TRUE(EVP_CIPHER_CTX_set_key_length(ctx.get(), key.size()));
|
||||
ASSERT_TRUE(EVP_CipherInit_ex(ctx.get(), nullptr, nullptr, key.data(),
|
||||
iv.data(), -1));
|
||||
// Note: the deprecated |EVP_CIPHER|-based AES-GCM API is sensitive to whether
|
||||
// parameters are NULL, so it is important to skip the |in| and |aad|
|
||||
// |EVP_CipherUpdate| calls when empty.
|
||||
if (!aad.empty()) {
|
||||
ASSERT_TRUE(
|
||||
EVP_CipherUpdate(ctx.get(), nullptr, &unused, aad.data(), aad.size()));
|
||||
}
|
||||
ASSERT_TRUE(EVP_CIPHER_CTX_set_padding(ctx.get(), 0));
|
||||
if (chunk_size != 0) {
|
||||
for (size_t i = 0; i < in->size();) {
|
||||
size_t todo = chunk_size;
|
||||
if (i + todo > in->size()) {
|
||||
todo = in->size() - i;
|
||||
}
|
||||
|
||||
int len;
|
||||
ASSERT_TRUE(EVP_CipherUpdate(ctx.get(), result.data() + result_len1, &len,
|
||||
in->data() + i, todo));
|
||||
result_len1 += len;
|
||||
i += todo;
|
||||
}
|
||||
} else if (!in->empty()) {
|
||||
ASSERT_TRUE(EVP_CipherUpdate(ctx.get(), result.data(), &result_len1,
|
||||
in->data(), in->size()));
|
||||
}
|
||||
ASSERT_TRUE(
|
||||
EVP_CipherFinal_ex(ctx.get(), result.data() + result_len1, &result_len2));
|
||||
result.resize(result_len1 + result_len2);
|
||||
EXPECT_EQ(Bytes(*out), Bytes(result));
|
||||
if (encrypt && is_aead) {
|
||||
uint8_t rtag[16];
|
||||
ASSERT_LE(tag.size(), sizeof(rtag));
|
||||
ASSERT_TRUE(
|
||||
EVP_CIPHER_CTX_ctrl(ctx.get(), EVP_CTRL_GCM_GET_TAG, tag.size(), rtag));
|
||||
EXPECT_EQ(Bytes(tag), Bytes(rtag, tag.size()));
|
||||
}
|
||||
}
|
||||
|
||||
static void TestCipher(FileTest *t) {
|
||||
std::string cipher_str;
|
||||
ASSERT_TRUE(t->GetAttribute(&cipher_str, "Cipher"));
|
||||
const EVP_CIPHER *cipher = GetCipher(cipher_str);
|
||||
ASSERT_TRUE(cipher);
|
||||
|
||||
std::vector<uint8_t> key, iv, plaintext, ciphertext, aad, tag;
|
||||
ASSERT_TRUE(t->GetBytes(&key, "Key"));
|
||||
ASSERT_TRUE(t->GetBytes(&plaintext, "Plaintext"));
|
||||
ASSERT_TRUE(t->GetBytes(&ciphertext, "Ciphertext"));
|
||||
if (EVP_CIPHER_iv_length(cipher) > 0) {
|
||||
ASSERT_TRUE(t->GetBytes(&iv, "IV"));
|
||||
}
|
||||
if (EVP_CIPHER_mode(cipher) == EVP_CIPH_GCM_MODE) {
|
||||
ASSERT_TRUE(t->GetBytes(&aad, "AAD"));
|
||||
ASSERT_TRUE(t->GetBytes(&tag, "Tag"));
|
||||
}
|
||||
|
||||
enum {
|
||||
kEncrypt,
|
||||
kDecrypt,
|
||||
kBoth,
|
||||
} operation = kBoth;
|
||||
if (t->HasAttribute("Operation")) {
|
||||
const std::string &str = t->GetAttributeOrDie("Operation");
|
||||
if (str == "ENCRYPT") {
|
||||
operation = kEncrypt;
|
||||
} else if (str == "DECRYPT") {
|
||||
operation = kDecrypt;
|
||||
} else {
|
||||
FAIL() << "Unknown operation: " << str;
|
||||
}
|
||||
}
|
||||
|
||||
const std::vector<size_t> chunk_sizes = {0, 1, 2, 5, 7, 8, 9, 15, 16,
|
||||
17, 31, 32, 33, 63, 64, 65, 512};
|
||||
|
||||
for (size_t chunk_size : chunk_sizes) {
|
||||
SCOPED_TRACE(chunk_size);
|
||||
// By default, both directions are run, unless overridden by the operation.
|
||||
if (operation != kDecrypt) {
|
||||
SCOPED_TRACE("encrypt");
|
||||
TestOperation(t, cipher, true /* encrypt */, chunk_size, key, iv,
|
||||
plaintext, ciphertext, aad, tag);
|
||||
}
|
||||
|
||||
if (operation != kEncrypt) {
|
||||
SCOPED_TRACE("decrypt");
|
||||
TestOperation(t, cipher, false /* decrypt */, chunk_size, key, iv,
|
||||
plaintext, ciphertext, aad, tag);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST(CipherTest, TestVectors) {
|
||||
FileTestGTest("crypto/cipher_extra/test/cipher_tests.txt", TestCipher);
|
||||
}
|
||||
|
||||
TEST(CipherTest, CAVP_AES_128_CBC) {
|
||||
FileTestGTest("crypto/cipher_extra/test/nist_cavp/aes_128_cbc.txt",
|
||||
TestCipher);
|
||||
}
|
||||
|
||||
TEST(CipherTest, CAVP_AES_128_CTR) {
|
||||
FileTestGTest("crypto/cipher_extra/test/nist_cavp/aes_128_ctr.txt",
|
||||
TestCipher);
|
||||
}
|
||||
|
||||
TEST(CipherTest, CAVP_AES_192_CBC) {
|
||||
FileTestGTest("crypto/cipher_extra/test/nist_cavp/aes_192_cbc.txt",
|
||||
TestCipher);
|
||||
}
|
||||
|
||||
TEST(CipherTest, CAVP_AES_192_CTR) {
|
||||
FileTestGTest("crypto/cipher_extra/test/nist_cavp/aes_192_ctr.txt",
|
||||
TestCipher);
|
||||
}
|
||||
|
||||
TEST(CipherTest, CAVP_AES_256_CBC) {
|
||||
FileTestGTest("crypto/cipher_extra/test/nist_cavp/aes_256_cbc.txt",
|
||||
TestCipher);
|
||||
}
|
||||
|
||||
TEST(CipherTest, CAVP_AES_256_CTR) {
|
||||
FileTestGTest("crypto/cipher_extra/test/nist_cavp/aes_256_ctr.txt",
|
||||
TestCipher);
|
||||
}
|
||||
|
||||
TEST(CipherTest, CAVP_TDES_CBC) {
|
||||
FileTestGTest("crypto/cipher_extra/test/nist_cavp/tdes_cbc.txt", TestCipher);
|
||||
}
|
||||
|
||||
TEST(CipherTest, CAVP_TDES_ECB) {
|
||||
FileTestGTest("crypto/cipher_extra/test/nist_cavp/tdes_ecb.txt", TestCipher);
|
||||
}
|
||||
@@ -61,8 +61,6 @@
|
||||
#include <openssl/digest.h>
|
||||
#include <openssl/mem.h>
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
|
||||
#define PKCS5_SALT_LEN 8
|
||||
|
||||
@@ -0,0 +1,283 @@
|
||||
/* Copyright (c) 2017, Google Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
|
||||
|
||||
#include <openssl/aead.h>
|
||||
#include <openssl/cipher.h>
|
||||
#include <openssl/crypto.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/sha.h>
|
||||
|
||||
#include "../fipsmodule/cipher/internal.h"
|
||||
|
||||
|
||||
#define EVP_AEAD_AES_CTR_HMAC_SHA256_TAG_LEN SHA256_DIGEST_LENGTH
|
||||
#define EVP_AEAD_AES_CTR_HMAC_SHA256_NONCE_LEN 12
|
||||
|
||||
struct aead_aes_ctr_hmac_sha256_ctx {
|
||||
union {
|
||||
double align;
|
||||
AES_KEY ks;
|
||||
} ks;
|
||||
ctr128_f ctr;
|
||||
block128_f block;
|
||||
SHA256_CTX inner_init_state;
|
||||
SHA256_CTX outer_init_state;
|
||||
};
|
||||
|
||||
static void hmac_init(SHA256_CTX *out_inner, SHA256_CTX *out_outer,
|
||||
const uint8_t hmac_key[32]) {
|
||||
static const size_t hmac_key_len = 32;
|
||||
uint8_t block[SHA256_CBLOCK];
|
||||
OPENSSL_memcpy(block, hmac_key, hmac_key_len);
|
||||
OPENSSL_memset(block + hmac_key_len, 0x36, sizeof(block) - hmac_key_len);
|
||||
|
||||
unsigned i;
|
||||
for (i = 0; i < hmac_key_len; i++) {
|
||||
block[i] ^= 0x36;
|
||||
}
|
||||
|
||||
SHA256_Init(out_inner);
|
||||
SHA256_Update(out_inner, block, sizeof(block));
|
||||
|
||||
OPENSSL_memset(block + hmac_key_len, 0x5c, sizeof(block) - hmac_key_len);
|
||||
for (i = 0; i < hmac_key_len; i++) {
|
||||
block[i] ^= (0x36 ^ 0x5c);
|
||||
}
|
||||
|
||||
SHA256_Init(out_outer);
|
||||
SHA256_Update(out_outer, block, sizeof(block));
|
||||
}
|
||||
|
||||
static int aead_aes_ctr_hmac_sha256_init(EVP_AEAD_CTX *ctx, const uint8_t *key,
|
||||
size_t key_len, size_t tag_len) {
|
||||
struct aead_aes_ctr_hmac_sha256_ctx *aes_ctx;
|
||||
static const size_t hmac_key_len = 32;
|
||||
|
||||
if (key_len < hmac_key_len) {
|
||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_KEY_LENGTH);
|
||||
return 0; // EVP_AEAD_CTX_init should catch this.
|
||||
}
|
||||
|
||||
const size_t aes_key_len = key_len - hmac_key_len;
|
||||
if (aes_key_len != 16 && aes_key_len != 32) {
|
||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_KEY_LENGTH);
|
||||
return 0; // EVP_AEAD_CTX_init should catch this.
|
||||
}
|
||||
|
||||
if (tag_len == EVP_AEAD_DEFAULT_TAG_LENGTH) {
|
||||
tag_len = EVP_AEAD_AES_CTR_HMAC_SHA256_TAG_LEN;
|
||||
}
|
||||
|
||||
if (tag_len > EVP_AEAD_AES_CTR_HMAC_SHA256_TAG_LEN) {
|
||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TAG_TOO_LARGE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
aes_ctx = OPENSSL_malloc(sizeof(struct aead_aes_ctr_hmac_sha256_ctx));
|
||||
if (aes_ctx == NULL) {
|
||||
OPENSSL_PUT_ERROR(CIPHER, ERR_R_MALLOC_FAILURE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
aes_ctx->ctr =
|
||||
aes_ctr_set_key(&aes_ctx->ks.ks, NULL, &aes_ctx->block, key, aes_key_len);
|
||||
ctx->tag_len = tag_len;
|
||||
hmac_init(&aes_ctx->inner_init_state, &aes_ctx->outer_init_state,
|
||||
key + aes_key_len);
|
||||
|
||||
ctx->aead_state = aes_ctx;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void aead_aes_ctr_hmac_sha256_cleanup(EVP_AEAD_CTX *ctx) {
|
||||
struct aead_aes_ctr_hmac_sha256_ctx *aes_ctx = ctx->aead_state;
|
||||
OPENSSL_cleanse(aes_ctx, sizeof(struct aead_aes_ctr_hmac_sha256_ctx));
|
||||
OPENSSL_free(aes_ctx);
|
||||
}
|
||||
|
||||
static void hmac_update_uint64(SHA256_CTX *sha256, uint64_t value) {
|
||||
unsigned i;
|
||||
uint8_t bytes[8];
|
||||
|
||||
for (i = 0; i < sizeof(bytes); i++) {
|
||||
bytes[i] = value & 0xff;
|
||||
value >>= 8;
|
||||
}
|
||||
SHA256_Update(sha256, bytes, sizeof(bytes));
|
||||
}
|
||||
|
||||
static void hmac_calculate(uint8_t out[SHA256_DIGEST_LENGTH],
|
||||
const SHA256_CTX *inner_init_state,
|
||||
const SHA256_CTX *outer_init_state,
|
||||
const uint8_t *ad, size_t ad_len,
|
||||
const uint8_t *nonce, const uint8_t *ciphertext,
|
||||
size_t ciphertext_len) {
|
||||
SHA256_CTX sha256;
|
||||
OPENSSL_memcpy(&sha256, inner_init_state, sizeof(sha256));
|
||||
hmac_update_uint64(&sha256, ad_len);
|
||||
hmac_update_uint64(&sha256, ciphertext_len);
|
||||
SHA256_Update(&sha256, nonce, EVP_AEAD_AES_CTR_HMAC_SHA256_NONCE_LEN);
|
||||
SHA256_Update(&sha256, ad, ad_len);
|
||||
|
||||
// Pad with zeros to the end of the SHA-256 block.
|
||||
const unsigned num_padding =
|
||||
(SHA256_CBLOCK - ((sizeof(uint64_t)*2 +
|
||||
EVP_AEAD_AES_CTR_HMAC_SHA256_NONCE_LEN + ad_len) %
|
||||
SHA256_CBLOCK)) %
|
||||
SHA256_CBLOCK;
|
||||
uint8_t padding[SHA256_CBLOCK];
|
||||
OPENSSL_memset(padding, 0, num_padding);
|
||||
SHA256_Update(&sha256, padding, num_padding);
|
||||
|
||||
SHA256_Update(&sha256, ciphertext, ciphertext_len);
|
||||
|
||||
uint8_t inner_digest[SHA256_DIGEST_LENGTH];
|
||||
SHA256_Final(inner_digest, &sha256);
|
||||
|
||||
OPENSSL_memcpy(&sha256, outer_init_state, sizeof(sha256));
|
||||
SHA256_Update(&sha256, inner_digest, sizeof(inner_digest));
|
||||
SHA256_Final(out, &sha256);
|
||||
}
|
||||
|
||||
static void aead_aes_ctr_hmac_sha256_crypt(
|
||||
const struct aead_aes_ctr_hmac_sha256_ctx *aes_ctx, uint8_t *out,
|
||||
const uint8_t *in, size_t len, const uint8_t *nonce) {
|
||||
// Since the AEAD operation is one-shot, keeping a buffer of unused keystream
|
||||
// bytes is pointless. However, |CRYPTO_ctr128_encrypt| requires it.
|
||||
uint8_t partial_block_buffer[AES_BLOCK_SIZE];
|
||||
unsigned partial_block_offset = 0;
|
||||
OPENSSL_memset(partial_block_buffer, 0, sizeof(partial_block_buffer));
|
||||
|
||||
uint8_t counter[AES_BLOCK_SIZE];
|
||||
OPENSSL_memcpy(counter, nonce, EVP_AEAD_AES_CTR_HMAC_SHA256_NONCE_LEN);
|
||||
OPENSSL_memset(counter + EVP_AEAD_AES_CTR_HMAC_SHA256_NONCE_LEN, 0, 4);
|
||||
|
||||
if (aes_ctx->ctr) {
|
||||
CRYPTO_ctr128_encrypt_ctr32(in, out, len, &aes_ctx->ks.ks, counter,
|
||||
partial_block_buffer, &partial_block_offset,
|
||||
aes_ctx->ctr);
|
||||
} else {
|
||||
CRYPTO_ctr128_encrypt(in, out, len, &aes_ctx->ks.ks, counter,
|
||||
partial_block_buffer, &partial_block_offset,
|
||||
aes_ctx->block);
|
||||
}
|
||||
}
|
||||
|
||||
static int aead_aes_ctr_hmac_sha256_seal_scatter(
|
||||
const EVP_AEAD_CTX *ctx, uint8_t *out, uint8_t *out_tag,
|
||||
size_t *out_tag_len, size_t max_out_tag_len, const uint8_t *nonce,
|
||||
size_t nonce_len, const uint8_t *in, size_t in_len, const uint8_t *extra_in,
|
||||
size_t extra_in_len, const uint8_t *ad, size_t ad_len) {
|
||||
const struct aead_aes_ctr_hmac_sha256_ctx *aes_ctx = ctx->aead_state;
|
||||
const uint64_t in_len_64 = in_len;
|
||||
|
||||
if (in_len_64 >= (UINT64_C(1) << 32) * AES_BLOCK_SIZE) {
|
||||
// This input is so large it would overflow the 32-bit block counter.
|
||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (max_out_tag_len < ctx->tag_len) {
|
||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BUFFER_TOO_SMALL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (nonce_len != EVP_AEAD_AES_CTR_HMAC_SHA256_NONCE_LEN) {
|
||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_UNSUPPORTED_NONCE_SIZE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
aead_aes_ctr_hmac_sha256_crypt(aes_ctx, out, in, in_len, nonce);
|
||||
|
||||
uint8_t hmac_result[SHA256_DIGEST_LENGTH];
|
||||
hmac_calculate(hmac_result, &aes_ctx->inner_init_state,
|
||||
&aes_ctx->outer_init_state, ad, ad_len, nonce, out, in_len);
|
||||
OPENSSL_memcpy(out_tag, hmac_result, ctx->tag_len);
|
||||
*out_tag_len = ctx->tag_len;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int aead_aes_ctr_hmac_sha256_open_gather(
|
||||
const EVP_AEAD_CTX *ctx, uint8_t *out, const uint8_t *nonce,
|
||||
size_t nonce_len, const uint8_t *in, size_t in_len, const uint8_t *in_tag,
|
||||
size_t in_tag_len, const uint8_t *ad, size_t ad_len) {
|
||||
const struct aead_aes_ctr_hmac_sha256_ctx *aes_ctx = ctx->aead_state;
|
||||
|
||||
if (in_tag_len != ctx->tag_len) {
|
||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (nonce_len != EVP_AEAD_AES_CTR_HMAC_SHA256_NONCE_LEN) {
|
||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_UNSUPPORTED_NONCE_SIZE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t hmac_result[SHA256_DIGEST_LENGTH];
|
||||
hmac_calculate(hmac_result, &aes_ctx->inner_init_state,
|
||||
&aes_ctx->outer_init_state, ad, ad_len, nonce, in,
|
||||
in_len);
|
||||
if (CRYPTO_memcmp(hmac_result, in_tag, ctx->tag_len) != 0) {
|
||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT);
|
||||
return 0;
|
||||
}
|
||||
|
||||
aead_aes_ctr_hmac_sha256_crypt(aes_ctx, out, in, in_len, nonce);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const EVP_AEAD aead_aes_128_ctr_hmac_sha256 = {
|
||||
16 /* AES key */ + 32 /* HMAC key */,
|
||||
12, // nonce length
|
||||
EVP_AEAD_AES_CTR_HMAC_SHA256_TAG_LEN, // overhead
|
||||
EVP_AEAD_AES_CTR_HMAC_SHA256_TAG_LEN, // max tag length
|
||||
0, // seal_scatter_supports_extra_in
|
||||
|
||||
aead_aes_ctr_hmac_sha256_init,
|
||||
NULL /* init_with_direction */,
|
||||
aead_aes_ctr_hmac_sha256_cleanup,
|
||||
NULL /* open */,
|
||||
aead_aes_ctr_hmac_sha256_seal_scatter,
|
||||
aead_aes_ctr_hmac_sha256_open_gather,
|
||||
NULL /* get_iv */,
|
||||
NULL /* tag_len */,
|
||||
};
|
||||
|
||||
static const EVP_AEAD aead_aes_256_ctr_hmac_sha256 = {
|
||||
32 /* AES key */ + 32 /* HMAC key */,
|
||||
12, // nonce length
|
||||
EVP_AEAD_AES_CTR_HMAC_SHA256_TAG_LEN, // overhead
|
||||
EVP_AEAD_AES_CTR_HMAC_SHA256_TAG_LEN, // max tag length
|
||||
0, // seal_scatter_supports_extra_in
|
||||
|
||||
aead_aes_ctr_hmac_sha256_init,
|
||||
NULL /* init_with_direction */,
|
||||
aead_aes_ctr_hmac_sha256_cleanup,
|
||||
NULL /* open */,
|
||||
aead_aes_ctr_hmac_sha256_seal_scatter,
|
||||
aead_aes_ctr_hmac_sha256_open_gather,
|
||||
NULL /* get_iv */,
|
||||
NULL /* tag_len */,
|
||||
};
|
||||
|
||||
const EVP_AEAD *EVP_aead_aes_128_ctr_hmac_sha256(void) {
|
||||
return &aead_aes_128_ctr_hmac_sha256;
|
||||
}
|
||||
|
||||
const EVP_AEAD *EVP_aead_aes_256_ctr_hmac_sha256(void) {
|
||||
return &aead_aes_256_ctr_hmac_sha256;
|
||||
}
|
||||
@@ -0,0 +1,862 @@
|
||||
/* Copyright (c) 2017, Google Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
|
||||
|
||||
#include <openssl/aead.h>
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include <openssl/cipher.h>
|
||||
#include <openssl/cpu.h>
|
||||
#include <openssl/crypto.h>
|
||||
#include <openssl/err.h>
|
||||
|
||||
#include "../fipsmodule/cipher/internal.h"
|
||||
|
||||
|
||||
#define EVP_AEAD_AES_GCM_SIV_NONCE_LEN 12
|
||||
#define EVP_AEAD_AES_GCM_SIV_TAG_LEN 16
|
||||
|
||||
#if defined(OPENSSL_X86_64) && !defined(OPENSSL_NO_ASM)
|
||||
|
||||
// Optimised AES-GCM-SIV
|
||||
|
||||
struct aead_aes_gcm_siv_asm_ctx {
|
||||
alignas(16) uint8_t key[16*15];
|
||||
int is_128_bit;
|
||||
};
|
||||
|
||||
// aes128gcmsiv_aes_ks writes an AES-128 key schedule for |key| to
|
||||
// |out_expanded_key|.
|
||||
extern void aes128gcmsiv_aes_ks(
|
||||
const uint8_t key[16], uint8_t out_expanded_key[16*15]);
|
||||
|
||||
// aes128gcmsiv_aes_ks writes an AES-128 key schedule for |key| to
|
||||
// |out_expanded_key|.
|
||||
extern void aes256gcmsiv_aes_ks(
|
||||
const uint8_t key[16], uint8_t out_expanded_key[16*15]);
|
||||
|
||||
static int aead_aes_gcm_siv_asm_init(EVP_AEAD_CTX *ctx, const uint8_t *key,
|
||||
size_t key_len, size_t tag_len) {
|
||||
const size_t key_bits = key_len * 8;
|
||||
|
||||
if (key_bits != 128 && key_bits != 256) {
|
||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_KEY_LENGTH);
|
||||
return 0; // EVP_AEAD_CTX_init should catch this.
|
||||
}
|
||||
|
||||
if (tag_len == EVP_AEAD_DEFAULT_TAG_LENGTH) {
|
||||
tag_len = EVP_AEAD_AES_GCM_SIV_TAG_LEN;
|
||||
}
|
||||
|
||||
if (tag_len != EVP_AEAD_AES_GCM_SIV_TAG_LEN) {
|
||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TAG_TOO_LARGE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct aead_aes_gcm_siv_asm_ctx *gcm_siv_ctx =
|
||||
OPENSSL_malloc(sizeof(struct aead_aes_gcm_siv_asm_ctx));
|
||||
if (gcm_siv_ctx == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// malloc should return a 16-byte-aligned address.
|
||||
assert((((uintptr_t)gcm_siv_ctx) & 15) == 0);
|
||||
|
||||
if (key_bits == 128) {
|
||||
aes128gcmsiv_aes_ks(key, &gcm_siv_ctx->key[0]);
|
||||
gcm_siv_ctx->is_128_bit = 1;
|
||||
} else {
|
||||
aes256gcmsiv_aes_ks(key, &gcm_siv_ctx->key[0]);
|
||||
gcm_siv_ctx->is_128_bit = 0;
|
||||
}
|
||||
ctx->aead_state = gcm_siv_ctx;
|
||||
ctx->tag_len = tag_len;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void aead_aes_gcm_siv_asm_cleanup(EVP_AEAD_CTX *ctx) {
|
||||
struct aead_aes_gcm_siv_asm_ctx *gcm_siv_asm_ctx = ctx->aead_state;
|
||||
OPENSSL_cleanse(gcm_siv_asm_ctx, sizeof(struct aead_aes_gcm_siv_asm_ctx));
|
||||
OPENSSL_free(gcm_siv_asm_ctx);
|
||||
}
|
||||
|
||||
// aesgcmsiv_polyval_horner updates the POLYVAL value in |in_out_poly| to
|
||||
// include a number (|in_blocks|) of 16-byte blocks of data from |in|, given
|
||||
// the POLYVAL key in |key|.
|
||||
extern void aesgcmsiv_polyval_horner(const uint8_t in_out_poly[16],
|
||||
const uint8_t key[16], const uint8_t *in,
|
||||
size_t in_blocks);
|
||||
|
||||
// aesgcmsiv_htable_init writes powers 1..8 of |auth_key| to |out_htable|.
|
||||
extern void aesgcmsiv_htable_init(uint8_t out_htable[16 * 8],
|
||||
const uint8_t auth_key[16]);
|
||||
|
||||
// aesgcmsiv_htable6_init writes powers 1..6 of |auth_key| to |out_htable|.
|
||||
extern void aesgcmsiv_htable6_init(uint8_t out_htable[16 * 6],
|
||||
const uint8_t auth_key[16]);
|
||||
|
||||
// aesgcmsiv_htable_polyval updates the POLYVAL value in |in_out_poly| to
|
||||
// include |in_len| bytes of data from |in|. (Where |in_len| must be a multiple
|
||||
// of 16.) It uses the precomputed powers of the key given in |htable|.
|
||||
extern void aesgcmsiv_htable_polyval(const uint8_t htable[16 * 8],
|
||||
const uint8_t *in, size_t in_len,
|
||||
uint8_t in_out_poly[16]);
|
||||
|
||||
// aes128gcmsiv_dec decrypts |in_len| & ~15 bytes from |out| and writes them to
|
||||
// |in|. (The full value of |in_len| is still used to find the authentication
|
||||
// tag appended to the ciphertext, however, so must not be pre-masked.)
|
||||
//
|
||||
// |in| and |out| may be equal, but must not otherwise overlap.
|
||||
//
|
||||
// While decrypting, it updates the POLYVAL value found at the beginning of
|
||||
// |in_out_calculated_tag_and_scratch| and writes the updated value back before
|
||||
// return. During executation, it may use the whole of this space for other
|
||||
// purposes. In order to decrypt and update the POLYVAL value, it uses the
|
||||
// expanded key from |key| and the table of powers in |htable|.
|
||||
extern void aes128gcmsiv_dec(const uint8_t *in, uint8_t *out,
|
||||
uint8_t in_out_calculated_tag_and_scratch[16 * 8],
|
||||
const uint8_t htable[16 * 6],
|
||||
const struct aead_aes_gcm_siv_asm_ctx *key,
|
||||
size_t in_len);
|
||||
|
||||
// aes256gcmsiv_dec acts like |aes128gcmsiv_dec|, but for AES-256.
|
||||
extern void aes256gcmsiv_dec(const uint8_t *in, uint8_t *out,
|
||||
uint8_t in_out_calculated_tag_and_scratch[16 * 8],
|
||||
const uint8_t htable[16 * 6],
|
||||
const struct aead_aes_gcm_siv_asm_ctx *key,
|
||||
size_t in_len);
|
||||
|
||||
// aes128gcmsiv_kdf performs the AES-GCM-SIV KDF given the expanded key from
|
||||
// |key_schedule| and the nonce in |nonce|. Note that, while only 12 bytes of
|
||||
// the nonce are used, 16 bytes are read and so the value must be
|
||||
// right-padded.
|
||||
extern void aes128gcmsiv_kdf(const uint8_t nonce[16],
|
||||
uint64_t out_key_material[8],
|
||||
const uint8_t *key_schedule);
|
||||
|
||||
// aes256gcmsiv_kdf acts like |aes128gcmsiv_kdf|, but for AES-256.
|
||||
extern void aes256gcmsiv_kdf(const uint8_t nonce[16],
|
||||
uint64_t out_key_material[12],
|
||||
const uint8_t *key_schedule);
|
||||
|
||||
// aes128gcmsiv_aes_ks_enc_x1 performs a key expansion of the AES-128 key in
|
||||
// |key|, writes the expanded key to |out_expanded_key| and encrypts a single
|
||||
// block from |in| to |out|.
|
||||
extern void aes128gcmsiv_aes_ks_enc_x1(const uint8_t in[16], uint8_t out[16],
|
||||
uint8_t out_expanded_key[16 * 15],
|
||||
const uint64_t key[2]);
|
||||
|
||||
// aes256gcmsiv_aes_ks_enc_x1 acts like |aes128gcmsiv_aes_ks_enc_x1|, but for
|
||||
// AES-256.
|
||||
extern void aes256gcmsiv_aes_ks_enc_x1(const uint8_t in[16], uint8_t out[16],
|
||||
uint8_t out_expanded_key[16 * 15],
|
||||
const uint64_t key[4]);
|
||||
|
||||
// aes128gcmsiv_ecb_enc_block encrypts a single block from |in| to |out| using
|
||||
// the expanded key in |expanded_key|.
|
||||
extern void aes128gcmsiv_ecb_enc_block(
|
||||
const uint8_t in[16], uint8_t out[16],
|
||||
const struct aead_aes_gcm_siv_asm_ctx *expanded_key);
|
||||
|
||||
// aes256gcmsiv_ecb_enc_block acts like |aes128gcmsiv_ecb_enc_block|, but for
|
||||
// AES-256.
|
||||
extern void aes256gcmsiv_ecb_enc_block(
|
||||
const uint8_t in[16], uint8_t out[16],
|
||||
const struct aead_aes_gcm_siv_asm_ctx *expanded_key);
|
||||
|
||||
// aes128gcmsiv_enc_msg_x4 encrypts |in_len| bytes from |in| to |out| using the
|
||||
// expanded key from |key|. (The value of |in_len| must be a multiple of 16.)
|
||||
// The |in| and |out| buffers may be equal but must not otherwise overlap. The
|
||||
// initial counter is constructed from the given |tag| as required by
|
||||
// AES-GCM-SIV.
|
||||
extern void aes128gcmsiv_enc_msg_x4(const uint8_t *in, uint8_t *out,
|
||||
const uint8_t *tag,
|
||||
const struct aead_aes_gcm_siv_asm_ctx *key,
|
||||
size_t in_len);
|
||||
|
||||
// aes256gcmsiv_enc_msg_x4 acts like |aes128gcmsiv_enc_msg_x4|, but for
|
||||
// AES-256.
|
||||
extern void aes256gcmsiv_enc_msg_x4(const uint8_t *in, uint8_t *out,
|
||||
const uint8_t *tag,
|
||||
const struct aead_aes_gcm_siv_asm_ctx *key,
|
||||
size_t in_len);
|
||||
|
||||
// aes128gcmsiv_enc_msg_x8 acts like |aes128gcmsiv_enc_msg_x4|, but is
|
||||
// optimised for longer messages.
|
||||
extern void aes128gcmsiv_enc_msg_x8(const uint8_t *in, uint8_t *out,
|
||||
const uint8_t *tag,
|
||||
const struct aead_aes_gcm_siv_asm_ctx *key,
|
||||
size_t in_len);
|
||||
|
||||
// aes256gcmsiv_enc_msg_x8 acts like |aes256gcmsiv_enc_msg_x4|, but is
|
||||
// optimised for longer messages.
|
||||
extern void aes256gcmsiv_enc_msg_x8(const uint8_t *in, uint8_t *out,
|
||||
const uint8_t *tag,
|
||||
const struct aead_aes_gcm_siv_asm_ctx *key,
|
||||
size_t in_len);
|
||||
|
||||
// gcm_siv_asm_polyval evaluates POLYVAL at |auth_key| on the given plaintext
|
||||
// and AD. The result is written to |out_tag|.
|
||||
static void gcm_siv_asm_polyval(uint8_t out_tag[16], const uint8_t *in,
|
||||
size_t in_len, const uint8_t *ad, size_t ad_len,
|
||||
const uint8_t auth_key[16],
|
||||
const uint8_t nonce[12]) {
|
||||
OPENSSL_memset(out_tag, 0, 16);
|
||||
const size_t ad_blocks = ad_len / 16;
|
||||
const size_t in_blocks = in_len / 16;
|
||||
int htable_init = 0;
|
||||
alignas(16) uint8_t htable[16*8];
|
||||
|
||||
if (ad_blocks > 8 || in_blocks > 8) {
|
||||
htable_init = 1;
|
||||
aesgcmsiv_htable_init(htable, auth_key);
|
||||
}
|
||||
|
||||
if (htable_init) {
|
||||
aesgcmsiv_htable_polyval(htable, ad, ad_len & ~15, out_tag);
|
||||
} else {
|
||||
aesgcmsiv_polyval_horner(out_tag, auth_key, ad, ad_blocks);
|
||||
}
|
||||
|
||||
uint8_t scratch[16];
|
||||
if (ad_len & 15) {
|
||||
OPENSSL_memset(scratch, 0, sizeof(scratch));
|
||||
OPENSSL_memcpy(scratch, &ad[ad_len & ~15], ad_len & 15);
|
||||
aesgcmsiv_polyval_horner(out_tag, auth_key, scratch, 1);
|
||||
}
|
||||
|
||||
if (htable_init) {
|
||||
aesgcmsiv_htable_polyval(htable, in, in_len & ~15, out_tag);
|
||||
} else {
|
||||
aesgcmsiv_polyval_horner(out_tag, auth_key, in, in_blocks);
|
||||
}
|
||||
|
||||
if (in_len & 15) {
|
||||
OPENSSL_memset(scratch, 0, sizeof(scratch));
|
||||
OPENSSL_memcpy(scratch, &in[in_len & ~15], in_len & 15);
|
||||
aesgcmsiv_polyval_horner(out_tag, auth_key, scratch, 1);
|
||||
}
|
||||
|
||||
union {
|
||||
uint8_t c[16];
|
||||
struct {
|
||||
uint64_t ad;
|
||||
uint64_t in;
|
||||
} bitlens;
|
||||
} length_block;
|
||||
|
||||
length_block.bitlens.ad = ad_len * 8;
|
||||
length_block.bitlens.in = in_len * 8;
|
||||
aesgcmsiv_polyval_horner(out_tag, auth_key, length_block.c, 1);
|
||||
|
||||
for (size_t i = 0; i < 12; i++) {
|
||||
out_tag[i] ^= nonce[i];
|
||||
}
|
||||
|
||||
out_tag[15] &= 0x7f;
|
||||
}
|
||||
|
||||
// aead_aes_gcm_siv_asm_crypt_last_block handles the encryption/decryption
|
||||
// (same thing in CTR mode) of the final block of a plaintext/ciphertext. It
|
||||
// writes |in_len| & 15 bytes to |out| + |in_len|, based on an initial counter
|
||||
// derived from |tag|.
|
||||
static void aead_aes_gcm_siv_asm_crypt_last_block(
|
||||
int is_128_bit, uint8_t *out, const uint8_t *in, size_t in_len,
|
||||
const uint8_t tag[16],
|
||||
const struct aead_aes_gcm_siv_asm_ctx *enc_key_expanded) {
|
||||
alignas(16) union {
|
||||
uint8_t c[16];
|
||||
uint32_t u32[4];
|
||||
} counter;
|
||||
OPENSSL_memcpy(&counter, tag, sizeof(counter));
|
||||
counter.c[15] |= 0x80;
|
||||
counter.u32[0] += in_len / 16;
|
||||
|
||||
if (is_128_bit) {
|
||||
aes128gcmsiv_ecb_enc_block(&counter.c[0], &counter.c[0], enc_key_expanded);
|
||||
} else {
|
||||
aes256gcmsiv_ecb_enc_block(&counter.c[0], &counter.c[0], enc_key_expanded);
|
||||
}
|
||||
|
||||
const size_t last_bytes_offset = in_len & ~15;
|
||||
const size_t last_bytes_len = in_len & 15;
|
||||
uint8_t *last_bytes_out = &out[last_bytes_offset];
|
||||
const uint8_t *last_bytes_in = &in[last_bytes_offset];
|
||||
for (size_t i = 0; i < last_bytes_len; i++) {
|
||||
last_bytes_out[i] = last_bytes_in[i] ^ counter.c[i];
|
||||
}
|
||||
}
|
||||
|
||||
// aead_aes_gcm_siv_kdf calculates the record encryption and authentication
|
||||
// keys given the |nonce|.
|
||||
static void aead_aes_gcm_siv_kdf(
|
||||
int is_128_bit, const struct aead_aes_gcm_siv_asm_ctx *gcm_siv_ctx,
|
||||
uint64_t out_record_auth_key[2], uint64_t out_record_enc_key[4],
|
||||
const uint8_t nonce[12]) {
|
||||
alignas(16) uint8_t padded_nonce[16];
|
||||
OPENSSL_memcpy(padded_nonce, nonce, 12);
|
||||
|
||||
alignas(16) uint64_t key_material[12];
|
||||
if (is_128_bit) {
|
||||
aes128gcmsiv_kdf(padded_nonce, key_material, &gcm_siv_ctx->key[0]);
|
||||
out_record_enc_key[0] = key_material[4];
|
||||
out_record_enc_key[1] = key_material[6];
|
||||
} else {
|
||||
aes256gcmsiv_kdf(padded_nonce, key_material, &gcm_siv_ctx->key[0]);
|
||||
out_record_enc_key[0] = key_material[4];
|
||||
out_record_enc_key[1] = key_material[6];
|
||||
out_record_enc_key[2] = key_material[8];
|
||||
out_record_enc_key[3] = key_material[10];
|
||||
}
|
||||
|
||||
out_record_auth_key[0] = key_material[0];
|
||||
out_record_auth_key[1] = key_material[2];
|
||||
}
|
||||
|
||||
static int aead_aes_gcm_siv_asm_seal_scatter(
|
||||
const EVP_AEAD_CTX *ctx, uint8_t *out, uint8_t *out_tag,
|
||||
size_t *out_tag_len, size_t max_out_tag_len, const uint8_t *nonce,
|
||||
size_t nonce_len, const uint8_t *in, size_t in_len, const uint8_t *extra_in,
|
||||
size_t extra_in_len, const uint8_t *ad, size_t ad_len) {
|
||||
const struct aead_aes_gcm_siv_asm_ctx *gcm_siv_ctx = ctx->aead_state;
|
||||
const uint64_t in_len_64 = in_len;
|
||||
const uint64_t ad_len_64 = ad_len;
|
||||
|
||||
if (in_len_64 > (UINT64_C(1) << 36) ||
|
||||
ad_len_64 >= (UINT64_C(1) << 61)) {
|
||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (max_out_tag_len < EVP_AEAD_AES_GCM_SIV_TAG_LEN) {
|
||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BUFFER_TOO_SMALL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (nonce_len != EVP_AEAD_AES_GCM_SIV_NONCE_LEN) {
|
||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_UNSUPPORTED_NONCE_SIZE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
alignas(16) uint64_t record_auth_key[2];
|
||||
alignas(16) uint64_t record_enc_key[4];
|
||||
aead_aes_gcm_siv_kdf(gcm_siv_ctx->is_128_bit, gcm_siv_ctx, record_auth_key,
|
||||
record_enc_key, nonce);
|
||||
|
||||
alignas(16) uint8_t tag[16] = {0};
|
||||
gcm_siv_asm_polyval(tag, in, in_len, ad, ad_len,
|
||||
(const uint8_t *)record_auth_key, nonce);
|
||||
|
||||
struct aead_aes_gcm_siv_asm_ctx enc_key_expanded;
|
||||
|
||||
if (gcm_siv_ctx->is_128_bit) {
|
||||
aes128gcmsiv_aes_ks_enc_x1(tag, tag, &enc_key_expanded.key[0],
|
||||
record_enc_key);
|
||||
|
||||
if (in_len < 128) {
|
||||
aes128gcmsiv_enc_msg_x4(in, out, tag, &enc_key_expanded, in_len & ~15);
|
||||
} else {
|
||||
aes128gcmsiv_enc_msg_x8(in, out, tag, &enc_key_expanded, in_len & ~15);
|
||||
}
|
||||
} else {
|
||||
aes256gcmsiv_aes_ks_enc_x1(tag, tag, &enc_key_expanded.key[0],
|
||||
record_enc_key);
|
||||
|
||||
if (in_len < 128) {
|
||||
aes256gcmsiv_enc_msg_x4(in, out, tag, &enc_key_expanded, in_len & ~15);
|
||||
} else {
|
||||
aes256gcmsiv_enc_msg_x8(in, out, tag, &enc_key_expanded, in_len & ~15);
|
||||
}
|
||||
}
|
||||
|
||||
if (in_len & 15) {
|
||||
aead_aes_gcm_siv_asm_crypt_last_block(gcm_siv_ctx->is_128_bit, out, in,
|
||||
in_len, tag, &enc_key_expanded);
|
||||
}
|
||||
|
||||
OPENSSL_memcpy(out_tag, tag, sizeof(tag));
|
||||
*out_tag_len = EVP_AEAD_AES_GCM_SIV_TAG_LEN;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// TODO(martinkr): Add aead_aes_gcm_siv_asm_open_gather. N.B. aes128gcmsiv_dec
|
||||
// expects ciphertext and tag in a contiguous buffer.
|
||||
|
||||
static int aead_aes_gcm_siv_asm_open(const EVP_AEAD_CTX *ctx, uint8_t *out,
|
||||
size_t *out_len, size_t max_out_len,
|
||||
const uint8_t *nonce, size_t nonce_len,
|
||||
const uint8_t *in, size_t in_len,
|
||||
const uint8_t *ad, size_t ad_len) {
|
||||
const uint64_t ad_len_64 = ad_len;
|
||||
if (ad_len_64 >= (UINT64_C(1) << 61)) {
|
||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
const uint64_t in_len_64 = in_len;
|
||||
if (in_len < EVP_AEAD_AES_GCM_SIV_TAG_LEN ||
|
||||
in_len_64 > (UINT64_C(1) << 36) + AES_BLOCK_SIZE) {
|
||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT);
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct aead_aes_gcm_siv_asm_ctx *gcm_siv_ctx = ctx->aead_state;
|
||||
const size_t plaintext_len = in_len - EVP_AEAD_AES_GCM_SIV_TAG_LEN;
|
||||
const uint8_t *const given_tag = in + plaintext_len;
|
||||
|
||||
if (max_out_len < plaintext_len) {
|
||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BUFFER_TOO_SMALL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
alignas(16) uint64_t record_auth_key[2];
|
||||
alignas(16) uint64_t record_enc_key[4];
|
||||
aead_aes_gcm_siv_kdf(gcm_siv_ctx->is_128_bit, gcm_siv_ctx, record_auth_key,
|
||||
record_enc_key, nonce);
|
||||
|
||||
struct aead_aes_gcm_siv_asm_ctx expanded_key;
|
||||
if (gcm_siv_ctx->is_128_bit) {
|
||||
aes128gcmsiv_aes_ks((const uint8_t *) record_enc_key, &expanded_key.key[0]);
|
||||
} else {
|
||||
aes256gcmsiv_aes_ks((const uint8_t *) record_enc_key, &expanded_key.key[0]);
|
||||
}
|
||||
// calculated_tag is 16*8 bytes, rather than 16 bytes, because
|
||||
// aes[128|256]gcmsiv_dec uses the extra as scratch space.
|
||||
alignas(16) uint8_t calculated_tag[16 * 8] = {0};
|
||||
|
||||
OPENSSL_memset(calculated_tag, 0, EVP_AEAD_AES_GCM_SIV_TAG_LEN);
|
||||
const size_t ad_blocks = ad_len / 16;
|
||||
aesgcmsiv_polyval_horner(calculated_tag, (const uint8_t *)record_auth_key, ad,
|
||||
ad_blocks);
|
||||
|
||||
uint8_t scratch[16];
|
||||
if (ad_len & 15) {
|
||||
OPENSSL_memset(scratch, 0, sizeof(scratch));
|
||||
OPENSSL_memcpy(scratch, &ad[ad_len & ~15], ad_len & 15);
|
||||
aesgcmsiv_polyval_horner(calculated_tag, (const uint8_t *)record_auth_key,
|
||||
scratch, 1);
|
||||
}
|
||||
|
||||
alignas(16) uint8_t htable[16 * 6];
|
||||
aesgcmsiv_htable6_init(htable, (const uint8_t *)record_auth_key);
|
||||
|
||||
if (gcm_siv_ctx->is_128_bit) {
|
||||
aes128gcmsiv_dec(in, out, calculated_tag, htable, &expanded_key,
|
||||
plaintext_len);
|
||||
} else {
|
||||
aes256gcmsiv_dec(in, out, calculated_tag, htable, &expanded_key,
|
||||
plaintext_len);
|
||||
}
|
||||
|
||||
if (plaintext_len & 15) {
|
||||
aead_aes_gcm_siv_asm_crypt_last_block(gcm_siv_ctx->is_128_bit, out, in,
|
||||
plaintext_len, given_tag,
|
||||
&expanded_key);
|
||||
OPENSSL_memset(scratch, 0, sizeof(scratch));
|
||||
OPENSSL_memcpy(scratch, out + (plaintext_len & ~15), plaintext_len & 15);
|
||||
aesgcmsiv_polyval_horner(calculated_tag, (const uint8_t *)record_auth_key,
|
||||
scratch, 1);
|
||||
}
|
||||
|
||||
union {
|
||||
uint8_t c[16];
|
||||
struct {
|
||||
uint64_t ad;
|
||||
uint64_t in;
|
||||
} bitlens;
|
||||
} length_block;
|
||||
|
||||
length_block.bitlens.ad = ad_len * 8;
|
||||
length_block.bitlens.in = plaintext_len * 8;
|
||||
aesgcmsiv_polyval_horner(calculated_tag, (const uint8_t *)record_auth_key,
|
||||
length_block.c, 1);
|
||||
|
||||
for (size_t i = 0; i < 12; i++) {
|
||||
calculated_tag[i] ^= nonce[i];
|
||||
}
|
||||
|
||||
calculated_tag[15] &= 0x7f;
|
||||
|
||||
if (gcm_siv_ctx->is_128_bit) {
|
||||
aes128gcmsiv_ecb_enc_block(calculated_tag, calculated_tag, &expanded_key);
|
||||
} else {
|
||||
aes256gcmsiv_ecb_enc_block(calculated_tag, calculated_tag, &expanded_key);
|
||||
}
|
||||
|
||||
if (CRYPTO_memcmp(calculated_tag, given_tag, EVP_AEAD_AES_GCM_SIV_TAG_LEN) !=
|
||||
0) {
|
||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT);
|
||||
return 0;
|
||||
}
|
||||
|
||||
*out_len = in_len - EVP_AEAD_AES_GCM_SIV_TAG_LEN;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const EVP_AEAD aead_aes_128_gcm_siv_asm = {
|
||||
16, // key length
|
||||
EVP_AEAD_AES_GCM_SIV_NONCE_LEN, // nonce length
|
||||
EVP_AEAD_AES_GCM_SIV_TAG_LEN, // overhead
|
||||
EVP_AEAD_AES_GCM_SIV_TAG_LEN, // max tag length
|
||||
0, // seal_scatter_supports_extra_in
|
||||
|
||||
aead_aes_gcm_siv_asm_init,
|
||||
NULL /* init_with_direction */,
|
||||
aead_aes_gcm_siv_asm_cleanup,
|
||||
aead_aes_gcm_siv_asm_open,
|
||||
aead_aes_gcm_siv_asm_seal_scatter,
|
||||
NULL /* open_gather */,
|
||||
NULL /* get_iv */,
|
||||
NULL /* tag_len */,
|
||||
};
|
||||
|
||||
static const EVP_AEAD aead_aes_256_gcm_siv_asm = {
|
||||
32, // key length
|
||||
EVP_AEAD_AES_GCM_SIV_NONCE_LEN, // nonce length
|
||||
EVP_AEAD_AES_GCM_SIV_TAG_LEN, // overhead
|
||||
EVP_AEAD_AES_GCM_SIV_TAG_LEN, // max tag length
|
||||
0, // seal_scatter_supports_extra_in
|
||||
|
||||
aead_aes_gcm_siv_asm_init,
|
||||
NULL /* init_with_direction */,
|
||||
aead_aes_gcm_siv_asm_cleanup,
|
||||
aead_aes_gcm_siv_asm_open,
|
||||
aead_aes_gcm_siv_asm_seal_scatter,
|
||||
NULL /* open_gather */,
|
||||
NULL /* get_iv */,
|
||||
NULL /* tag_len */,
|
||||
};
|
||||
|
||||
#endif // X86_64 && !NO_ASM
|
||||
|
||||
struct aead_aes_gcm_siv_ctx {
|
||||
union {
|
||||
double align;
|
||||
AES_KEY ks;
|
||||
} ks;
|
||||
block128_f kgk_block;
|
||||
unsigned is_256:1;
|
||||
};
|
||||
|
||||
static int aead_aes_gcm_siv_init(EVP_AEAD_CTX *ctx, const uint8_t *key,
|
||||
size_t key_len, size_t tag_len) {
|
||||
const size_t key_bits = key_len * 8;
|
||||
|
||||
if (key_bits != 128 && key_bits != 256) {
|
||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_KEY_LENGTH);
|
||||
return 0; // EVP_AEAD_CTX_init should catch this.
|
||||
}
|
||||
|
||||
if (tag_len == EVP_AEAD_DEFAULT_TAG_LENGTH) {
|
||||
tag_len = EVP_AEAD_AES_GCM_SIV_TAG_LEN;
|
||||
}
|
||||
if (tag_len != EVP_AEAD_AES_GCM_SIV_TAG_LEN) {
|
||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TAG_TOO_LARGE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct aead_aes_gcm_siv_ctx *gcm_siv_ctx =
|
||||
OPENSSL_malloc(sizeof(struct aead_aes_gcm_siv_ctx));
|
||||
if (gcm_siv_ctx == NULL) {
|
||||
return 0;
|
||||
}
|
||||
OPENSSL_memset(gcm_siv_ctx, 0, sizeof(struct aead_aes_gcm_siv_ctx));
|
||||
|
||||
aes_ctr_set_key(&gcm_siv_ctx->ks.ks, NULL, &gcm_siv_ctx->kgk_block, key,
|
||||
key_len);
|
||||
gcm_siv_ctx->is_256 = (key_len == 32);
|
||||
ctx->aead_state = gcm_siv_ctx;
|
||||
ctx->tag_len = tag_len;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void aead_aes_gcm_siv_cleanup(EVP_AEAD_CTX *ctx) {
|
||||
struct aead_aes_gcm_siv_ctx *gcm_siv_ctx = ctx->aead_state;
|
||||
OPENSSL_cleanse(gcm_siv_ctx, sizeof(struct aead_aes_gcm_siv_ctx));
|
||||
OPENSSL_free(gcm_siv_ctx);
|
||||
}
|
||||
|
||||
// gcm_siv_crypt encrypts (or decrypts—it's the same thing) |in_len| bytes from
|
||||
// |in| to |out|, using the block function |enc_block| with |key| in counter
|
||||
// mode, starting at |initial_counter|. This differs from the traditional
|
||||
// counter mode code in that the counter is handled little-endian, only the
|
||||
// first four bytes are used and the GCM-SIV tweak to the final byte is
|
||||
// applied. The |in| and |out| pointers may be equal but otherwise must not
|
||||
// alias.
|
||||
static void gcm_siv_crypt(uint8_t *out, const uint8_t *in, size_t in_len,
|
||||
const uint8_t initial_counter[AES_BLOCK_SIZE],
|
||||
block128_f enc_block, const AES_KEY *key) {
|
||||
union {
|
||||
uint32_t w[4];
|
||||
uint8_t c[16];
|
||||
} counter;
|
||||
|
||||
OPENSSL_memcpy(counter.c, initial_counter, AES_BLOCK_SIZE);
|
||||
counter.c[15] |= 0x80;
|
||||
|
||||
for (size_t done = 0; done < in_len;) {
|
||||
uint8_t keystream[AES_BLOCK_SIZE];
|
||||
enc_block(counter.c, keystream, key);
|
||||
counter.w[0]++;
|
||||
|
||||
size_t todo = AES_BLOCK_SIZE;
|
||||
if (in_len - done < todo) {
|
||||
todo = in_len - done;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < todo; i++) {
|
||||
out[done + i] = keystream[i] ^ in[done + i];
|
||||
}
|
||||
|
||||
done += todo;
|
||||
}
|
||||
}
|
||||
|
||||
// gcm_siv_polyval evaluates POLYVAL at |auth_key| on the given plaintext and
|
||||
// AD. The result is written to |out_tag|.
|
||||
static void gcm_siv_polyval(
|
||||
uint8_t out_tag[16], const uint8_t *in, size_t in_len, const uint8_t *ad,
|
||||
size_t ad_len, const uint8_t auth_key[16],
|
||||
const uint8_t nonce[EVP_AEAD_AES_GCM_SIV_NONCE_LEN]) {
|
||||
struct polyval_ctx polyval_ctx;
|
||||
CRYPTO_POLYVAL_init(&polyval_ctx, auth_key);
|
||||
|
||||
CRYPTO_POLYVAL_update_blocks(&polyval_ctx, ad, ad_len & ~15);
|
||||
|
||||
uint8_t scratch[16];
|
||||
if (ad_len & 15) {
|
||||
OPENSSL_memset(scratch, 0, sizeof(scratch));
|
||||
OPENSSL_memcpy(scratch, &ad[ad_len & ~15], ad_len & 15);
|
||||
CRYPTO_POLYVAL_update_blocks(&polyval_ctx, scratch, sizeof(scratch));
|
||||
}
|
||||
|
||||
CRYPTO_POLYVAL_update_blocks(&polyval_ctx, in, in_len & ~15);
|
||||
if (in_len & 15) {
|
||||
OPENSSL_memset(scratch, 0, sizeof(scratch));
|
||||
OPENSSL_memcpy(scratch, &in[in_len & ~15], in_len & 15);
|
||||
CRYPTO_POLYVAL_update_blocks(&polyval_ctx, scratch, sizeof(scratch));
|
||||
}
|
||||
|
||||
union {
|
||||
uint8_t c[16];
|
||||
struct {
|
||||
uint64_t ad;
|
||||
uint64_t in;
|
||||
} bitlens;
|
||||
} length_block;
|
||||
|
||||
length_block.bitlens.ad = ad_len * 8;
|
||||
length_block.bitlens.in = in_len * 8;
|
||||
CRYPTO_POLYVAL_update_blocks(&polyval_ctx, length_block.c,
|
||||
sizeof(length_block));
|
||||
|
||||
CRYPTO_POLYVAL_finish(&polyval_ctx, out_tag);
|
||||
for (size_t i = 0; i < EVP_AEAD_AES_GCM_SIV_NONCE_LEN; i++) {
|
||||
out_tag[i] ^= nonce[i];
|
||||
}
|
||||
out_tag[15] &= 0x7f;
|
||||
}
|
||||
|
||||
// gcm_siv_record_keys contains the keys used for a specific GCM-SIV record.
|
||||
struct gcm_siv_record_keys {
|
||||
uint8_t auth_key[16];
|
||||
union {
|
||||
double align;
|
||||
AES_KEY ks;
|
||||
} enc_key;
|
||||
block128_f enc_block;
|
||||
};
|
||||
|
||||
// gcm_siv_keys calculates the keys for a specific GCM-SIV record with the
|
||||
// given nonce and writes them to |*out_keys|.
|
||||
static void gcm_siv_keys(
|
||||
const struct aead_aes_gcm_siv_ctx *gcm_siv_ctx,
|
||||
struct gcm_siv_record_keys *out_keys,
|
||||
const uint8_t nonce[EVP_AEAD_AES_GCM_SIV_NONCE_LEN]) {
|
||||
const AES_KEY *const key = &gcm_siv_ctx->ks.ks;
|
||||
uint8_t key_material[(128 /* POLYVAL key */ + 256 /* max AES key */) / 8];
|
||||
const size_t blocks_needed = gcm_siv_ctx->is_256 ? 6 : 4;
|
||||
|
||||
uint8_t counter[AES_BLOCK_SIZE];
|
||||
OPENSSL_memset(counter, 0, AES_BLOCK_SIZE - EVP_AEAD_AES_GCM_SIV_NONCE_LEN);
|
||||
OPENSSL_memcpy(counter + AES_BLOCK_SIZE - EVP_AEAD_AES_GCM_SIV_NONCE_LEN,
|
||||
nonce, EVP_AEAD_AES_GCM_SIV_NONCE_LEN);
|
||||
for (size_t i = 0; i < blocks_needed; i++) {
|
||||
counter[0] = i;
|
||||
|
||||
uint8_t ciphertext[AES_BLOCK_SIZE];
|
||||
gcm_siv_ctx->kgk_block(counter, ciphertext, key);
|
||||
OPENSSL_memcpy(&key_material[i * 8], ciphertext, 8);
|
||||
}
|
||||
|
||||
OPENSSL_memcpy(out_keys->auth_key, key_material, 16);
|
||||
aes_ctr_set_key(&out_keys->enc_key.ks, NULL, &out_keys->enc_block,
|
||||
key_material + 16, gcm_siv_ctx->is_256 ? 32 : 16);
|
||||
}
|
||||
|
||||
static int aead_aes_gcm_siv_seal_scatter(
|
||||
const EVP_AEAD_CTX *ctx, uint8_t *out, uint8_t *out_tag,
|
||||
size_t *out_tag_len, size_t max_out_tag_len, const uint8_t *nonce,
|
||||
size_t nonce_len, const uint8_t *in, size_t in_len, const uint8_t *extra_in,
|
||||
size_t extra_in_len, const uint8_t *ad, size_t ad_len) {
|
||||
const struct aead_aes_gcm_siv_ctx *gcm_siv_ctx = ctx->aead_state;
|
||||
const uint64_t in_len_64 = in_len;
|
||||
const uint64_t ad_len_64 = ad_len;
|
||||
|
||||
if (in_len + EVP_AEAD_AES_GCM_SIV_TAG_LEN < in_len ||
|
||||
in_len_64 > (UINT64_C(1) << 36) ||
|
||||
ad_len_64 >= (UINT64_C(1) << 61)) {
|
||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (max_out_tag_len < EVP_AEAD_AES_GCM_SIV_TAG_LEN) {
|
||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BUFFER_TOO_SMALL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (nonce_len != EVP_AEAD_AES_GCM_SIV_NONCE_LEN) {
|
||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_UNSUPPORTED_NONCE_SIZE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct gcm_siv_record_keys keys;
|
||||
gcm_siv_keys(gcm_siv_ctx, &keys, nonce);
|
||||
|
||||
uint8_t tag[16];
|
||||
gcm_siv_polyval(tag, in, in_len, ad, ad_len, keys.auth_key, nonce);
|
||||
keys.enc_block(tag, tag, &keys.enc_key.ks);
|
||||
|
||||
gcm_siv_crypt(out, in, in_len, tag, keys.enc_block, &keys.enc_key.ks);
|
||||
|
||||
OPENSSL_memcpy(out_tag, tag, EVP_AEAD_AES_GCM_SIV_TAG_LEN);
|
||||
*out_tag_len = EVP_AEAD_AES_GCM_SIV_TAG_LEN;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int aead_aes_gcm_siv_open_gather(const EVP_AEAD_CTX *ctx, uint8_t *out,
|
||||
const uint8_t *nonce, size_t nonce_len,
|
||||
const uint8_t *in, size_t in_len,
|
||||
const uint8_t *in_tag,
|
||||
size_t in_tag_len, const uint8_t *ad,
|
||||
size_t ad_len) {
|
||||
const uint64_t ad_len_64 = ad_len;
|
||||
if (ad_len_64 >= (UINT64_C(1) << 61)) {
|
||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
const uint64_t in_len_64 = in_len;
|
||||
if (in_tag_len != EVP_AEAD_AES_GCM_SIV_TAG_LEN ||
|
||||
in_len_64 > (UINT64_C(1) << 36) + AES_BLOCK_SIZE) {
|
||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (nonce_len != EVP_AEAD_AES_GCM_SIV_NONCE_LEN) {
|
||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_UNSUPPORTED_NONCE_SIZE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct aead_aes_gcm_siv_ctx *gcm_siv_ctx = ctx->aead_state;
|
||||
|
||||
struct gcm_siv_record_keys keys;
|
||||
gcm_siv_keys(gcm_siv_ctx, &keys, nonce);
|
||||
|
||||
gcm_siv_crypt(out, in, in_len, in_tag, keys.enc_block, &keys.enc_key.ks);
|
||||
|
||||
uint8_t expected_tag[EVP_AEAD_AES_GCM_SIV_TAG_LEN];
|
||||
gcm_siv_polyval(expected_tag, out, in_len, ad, ad_len, keys.auth_key, nonce);
|
||||
keys.enc_block(expected_tag, expected_tag, &keys.enc_key.ks);
|
||||
|
||||
if (CRYPTO_memcmp(expected_tag, in_tag, sizeof(expected_tag)) != 0) {
|
||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const EVP_AEAD aead_aes_128_gcm_siv = {
|
||||
16, // key length
|
||||
EVP_AEAD_AES_GCM_SIV_NONCE_LEN, // nonce length
|
||||
EVP_AEAD_AES_GCM_SIV_TAG_LEN, // overhead
|
||||
EVP_AEAD_AES_GCM_SIV_TAG_LEN, // max tag length
|
||||
0, // seal_scatter_supports_extra_in
|
||||
|
||||
aead_aes_gcm_siv_init,
|
||||
NULL /* init_with_direction */,
|
||||
aead_aes_gcm_siv_cleanup,
|
||||
NULL /* open */,
|
||||
aead_aes_gcm_siv_seal_scatter,
|
||||
aead_aes_gcm_siv_open_gather,
|
||||
NULL /* get_iv */,
|
||||
NULL /* tag_len */,
|
||||
};
|
||||
|
||||
static const EVP_AEAD aead_aes_256_gcm_siv = {
|
||||
32, // key length
|
||||
EVP_AEAD_AES_GCM_SIV_NONCE_LEN, // nonce length
|
||||
EVP_AEAD_AES_GCM_SIV_TAG_LEN, // overhead
|
||||
EVP_AEAD_AES_GCM_SIV_TAG_LEN, // max tag length
|
||||
0, // seal_scatter_supports_extra_in
|
||||
|
||||
aead_aes_gcm_siv_init,
|
||||
NULL /* init_with_direction */,
|
||||
aead_aes_gcm_siv_cleanup,
|
||||
NULL /* open */,
|
||||
aead_aes_gcm_siv_seal_scatter,
|
||||
aead_aes_gcm_siv_open_gather,
|
||||
NULL /* get_iv */,
|
||||
NULL /* tag_len */,
|
||||
};
|
||||
|
||||
#if defined(OPENSSL_X86_64) && !defined(OPENSSL_NO_ASM)
|
||||
|
||||
static char avx_aesni_capable(void) {
|
||||
const uint32_t ecx = OPENSSL_ia32cap_P[1];
|
||||
|
||||
return (ecx & (1 << (57 - 32))) != 0 /* AESNI */ &&
|
||||
(ecx & (1 << 28)) != 0 /* AVX */;
|
||||
}
|
||||
|
||||
const EVP_AEAD *EVP_aead_aes_128_gcm_siv(void) {
|
||||
if (avx_aesni_capable()) {
|
||||
return &aead_aes_128_gcm_siv_asm;
|
||||
}
|
||||
return &aead_aes_128_gcm_siv;
|
||||
}
|
||||
|
||||
const EVP_AEAD *EVP_aead_aes_256_gcm_siv(void) {
|
||||
if (avx_aesni_capable()) {
|
||||
return &aead_aes_256_gcm_siv_asm;
|
||||
}
|
||||
return &aead_aes_256_gcm_siv;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
const EVP_AEAD *EVP_aead_aes_128_gcm_siv(void) {
|
||||
return &aead_aes_128_gcm_siv;
|
||||
}
|
||||
|
||||
const EVP_AEAD *EVP_aead_aes_256_gcm_siv(void) {
|
||||
return &aead_aes_256_gcm_siv;
|
||||
}
|
||||
|
||||
#endif // X86_64 && !NO_ASM
|
||||
@@ -0,0 +1,328 @@
|
||||
/* Copyright (c) 2014, Google Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
||||
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
|
||||
|
||||
#include <openssl/aead.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <openssl/chacha.h>
|
||||
#include <openssl/cipher.h>
|
||||
#include <openssl/cpu.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/mem.h>
|
||||
#include <openssl/poly1305.h>
|
||||
#include <openssl/type_check.h>
|
||||
|
||||
#include "../fipsmodule/cipher/internal.h"
|
||||
#include "../internal.h"
|
||||
|
||||
|
||||
#define POLY1305_TAG_LEN 16
|
||||
|
||||
struct aead_chacha20_poly1305_ctx {
|
||||
uint8_t key[32];
|
||||
};
|
||||
|
||||
// For convenience (the x86_64 calling convention allows only six parameters in
|
||||
// registers), the final parameter for the assembly functions is both an input
|
||||
// and output parameter.
|
||||
union open_data {
|
||||
struct {
|
||||
alignas(16) uint8_t key[32];
|
||||
uint32_t counter;
|
||||
uint8_t nonce[12];
|
||||
} in;
|
||||
struct {
|
||||
uint8_t tag[POLY1305_TAG_LEN];
|
||||
} out;
|
||||
};
|
||||
|
||||
union seal_data {
|
||||
struct {
|
||||
alignas(16) uint8_t key[32];
|
||||
uint32_t counter;
|
||||
uint8_t nonce[12];
|
||||
const uint8_t *extra_ciphertext;
|
||||
size_t extra_ciphertext_len;
|
||||
} in;
|
||||
struct {
|
||||
uint8_t tag[POLY1305_TAG_LEN];
|
||||
} out;
|
||||
};
|
||||
|
||||
#if defined(OPENSSL_X86_64) && !defined(OPENSSL_NO_ASM) && \
|
||||
!defined(OPENSSL_WINDOWS)
|
||||
static int asm_capable(void) {
|
||||
const int sse41_capable = (OPENSSL_ia32cap_P[1] & (1 << 19)) != 0;
|
||||
return sse41_capable;
|
||||
}
|
||||
|
||||
OPENSSL_COMPILE_ASSERT(sizeof(union open_data) == 48, wrong_open_data_size);
|
||||
OPENSSL_COMPILE_ASSERT(sizeof(union seal_data) == 48 + 8 + 8,
|
||||
wrong_seal_data_size);
|
||||
|
||||
// chacha20_poly1305_open is defined in chacha20_poly1305_x86_64.pl. It decrypts
|
||||
// |plaintext_len| bytes from |ciphertext| and writes them to |out_plaintext|.
|
||||
// Additional input parameters are passed in |aead_data->in|. On exit, it will
|
||||
// write calculated tag value to |aead_data->out.tag|, which the caller must
|
||||
// check.
|
||||
extern void chacha20_poly1305_open(uint8_t *out_plaintext,
|
||||
const uint8_t *ciphertext,
|
||||
size_t plaintext_len, const uint8_t *ad,
|
||||
size_t ad_len, union open_data *aead_data);
|
||||
|
||||
// chacha20_poly1305_open is defined in chacha20_poly1305_x86_64.pl. It encrypts
|
||||
// |plaintext_len| bytes from |plaintext| and writes them to |out_ciphertext|.
|
||||
// Additional input parameters are passed in |aead_data->in|. The calculated tag
|
||||
// value is over the computed ciphertext concatenated with |extra_ciphertext|
|
||||
// and written to |aead_data->out.tag|.
|
||||
extern void chacha20_poly1305_seal(uint8_t *out_ciphertext,
|
||||
const uint8_t *plaintext,
|
||||
size_t plaintext_len, const uint8_t *ad,
|
||||
size_t ad_len, union seal_data *aead_data);
|
||||
#else
|
||||
static int asm_capable(void) { return 0; }
|
||||
|
||||
|
||||
static void chacha20_poly1305_open(uint8_t *out_plaintext,
|
||||
const uint8_t *ciphertext,
|
||||
size_t plaintext_len, const uint8_t *ad,
|
||||
size_t ad_len, union open_data *aead_data) {}
|
||||
|
||||
static void chacha20_poly1305_seal(uint8_t *out_ciphertext,
|
||||
const uint8_t *plaintext,
|
||||
size_t plaintext_len, const uint8_t *ad,
|
||||
size_t ad_len, union seal_data *aead_data) {}
|
||||
#endif
|
||||
|
||||
static int aead_chacha20_poly1305_init(EVP_AEAD_CTX *ctx, const uint8_t *key,
|
||||
size_t key_len, size_t tag_len) {
|
||||
struct aead_chacha20_poly1305_ctx *c20_ctx;
|
||||
|
||||
if (tag_len == 0) {
|
||||
tag_len = POLY1305_TAG_LEN;
|
||||
}
|
||||
|
||||
if (tag_len > POLY1305_TAG_LEN) {
|
||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (key_len != sizeof(c20_ctx->key)) {
|
||||
return 0; // internal error - EVP_AEAD_CTX_init should catch this.
|
||||
}
|
||||
|
||||
c20_ctx = OPENSSL_malloc(sizeof(struct aead_chacha20_poly1305_ctx));
|
||||
if (c20_ctx == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
OPENSSL_memcpy(c20_ctx->key, key, key_len);
|
||||
ctx->aead_state = c20_ctx;
|
||||
ctx->tag_len = tag_len;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void aead_chacha20_poly1305_cleanup(EVP_AEAD_CTX *ctx) {
|
||||
struct aead_chacha20_poly1305_ctx *c20_ctx = ctx->aead_state;
|
||||
OPENSSL_cleanse(c20_ctx->key, sizeof(c20_ctx->key));
|
||||
OPENSSL_free(c20_ctx);
|
||||
}
|
||||
|
||||
static void poly1305_update_length(poly1305_state *poly1305, size_t data_len) {
|
||||
uint8_t length_bytes[8];
|
||||
|
||||
for (unsigned i = 0; i < sizeof(length_bytes); i++) {
|
||||
length_bytes[i] = data_len;
|
||||
data_len >>= 8;
|
||||
}
|
||||
|
||||
CRYPTO_poly1305_update(poly1305, length_bytes, sizeof(length_bytes));
|
||||
}
|
||||
|
||||
// calc_tag fills |tag| with the authentication tag for the given inputs.
|
||||
static void calc_tag(uint8_t tag[POLY1305_TAG_LEN],
|
||||
const struct aead_chacha20_poly1305_ctx *c20_ctx,
|
||||
const uint8_t nonce[12], const uint8_t *ad, size_t ad_len,
|
||||
const uint8_t *ciphertext, size_t ciphertext_len,
|
||||
const uint8_t *ciphertext_extra,
|
||||
size_t ciphertext_extra_len) {
|
||||
alignas(16) uint8_t poly1305_key[32];
|
||||
OPENSSL_memset(poly1305_key, 0, sizeof(poly1305_key));
|
||||
CRYPTO_chacha_20(poly1305_key, poly1305_key, sizeof(poly1305_key),
|
||||
c20_ctx->key, nonce, 0);
|
||||
|
||||
static const uint8_t padding[16] = { 0 }; // Padding is all zeros.
|
||||
poly1305_state ctx;
|
||||
CRYPTO_poly1305_init(&ctx, poly1305_key);
|
||||
CRYPTO_poly1305_update(&ctx, ad, ad_len);
|
||||
if (ad_len % 16 != 0) {
|
||||
CRYPTO_poly1305_update(&ctx, padding, sizeof(padding) - (ad_len % 16));
|
||||
}
|
||||
CRYPTO_poly1305_update(&ctx, ciphertext, ciphertext_len);
|
||||
CRYPTO_poly1305_update(&ctx, ciphertext_extra, ciphertext_extra_len);
|
||||
const size_t ciphertext_total = ciphertext_len + ciphertext_extra_len;
|
||||
if (ciphertext_total % 16 != 0) {
|
||||
CRYPTO_poly1305_update(&ctx, padding,
|
||||
sizeof(padding) - (ciphertext_total % 16));
|
||||
}
|
||||
poly1305_update_length(&ctx, ad_len);
|
||||
poly1305_update_length(&ctx, ciphertext_total);
|
||||
CRYPTO_poly1305_finish(&ctx, tag);
|
||||
}
|
||||
|
||||
static int aead_chacha20_poly1305_seal_scatter(
|
||||
const EVP_AEAD_CTX *ctx, uint8_t *out, uint8_t *out_tag,
|
||||
size_t *out_tag_len, size_t max_out_tag_len, const uint8_t *nonce,
|
||||
size_t nonce_len, const uint8_t *in, size_t in_len, const uint8_t *extra_in,
|
||||
size_t extra_in_len, const uint8_t *ad, size_t ad_len) {
|
||||
const struct aead_chacha20_poly1305_ctx *c20_ctx = ctx->aead_state;
|
||||
|
||||
if (extra_in_len + ctx->tag_len < ctx->tag_len) {
|
||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE);
|
||||
return 0;
|
||||
}
|
||||
if (max_out_tag_len < ctx->tag_len + extra_in_len) {
|
||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BUFFER_TOO_SMALL);
|
||||
return 0;
|
||||
}
|
||||
if (nonce_len != 12) {
|
||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_UNSUPPORTED_NONCE_SIZE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// |CRYPTO_chacha_20| uses a 32-bit block counter. Therefore we disallow
|
||||
// individual operations that work on more than 256GB at a time.
|
||||
// |in_len_64| is needed because, on 32-bit platforms, size_t is only
|
||||
// 32-bits and this produces a warning because it's always false.
|
||||
// Casting to uint64_t inside the conditional is not sufficient to stop
|
||||
// the warning.
|
||||
const uint64_t in_len_64 = in_len;
|
||||
if (in_len_64 >= (UINT64_C(1) << 32) * 64 - 64) {
|
||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (max_out_tag_len < ctx->tag_len) {
|
||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BUFFER_TOO_SMALL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// The the extra input is given, it is expected to be very short and so is
|
||||
// encrypted byte-by-byte first.
|
||||
if (extra_in_len) {
|
||||
static const size_t kChaChaBlockSize = 64;
|
||||
uint32_t block_counter = 1 + (in_len / kChaChaBlockSize);
|
||||
size_t offset = in_len % kChaChaBlockSize;
|
||||
uint8_t block[64 /* kChaChaBlockSize */];
|
||||
|
||||
for (size_t done = 0; done < extra_in_len; block_counter++) {
|
||||
memset(block, 0, sizeof(block));
|
||||
CRYPTO_chacha_20(block, block, sizeof(block), c20_ctx->key, nonce,
|
||||
block_counter);
|
||||
for (size_t i = offset; i < sizeof(block) && done < extra_in_len;
|
||||
i++, done++) {
|
||||
out_tag[done] = extra_in[done] ^ block[i];
|
||||
}
|
||||
offset = 0;
|
||||
}
|
||||
}
|
||||
|
||||
union seal_data data;
|
||||
if (asm_capable()) {
|
||||
OPENSSL_memcpy(data.in.key, c20_ctx->key, 32);
|
||||
data.in.counter = 0;
|
||||
OPENSSL_memcpy(data.in.nonce, nonce, 12);
|
||||
data.in.extra_ciphertext = out_tag;
|
||||
data.in.extra_ciphertext_len = extra_in_len;
|
||||
chacha20_poly1305_seal(out, in, in_len, ad, ad_len, &data);
|
||||
} else {
|
||||
CRYPTO_chacha_20(out, in, in_len, c20_ctx->key, nonce, 1);
|
||||
calc_tag(data.out.tag, c20_ctx, nonce, ad, ad_len, out, in_len, out_tag,
|
||||
extra_in_len);
|
||||
}
|
||||
|
||||
OPENSSL_memcpy(out_tag + extra_in_len, data.out.tag, ctx->tag_len);
|
||||
*out_tag_len = extra_in_len + ctx->tag_len;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int aead_chacha20_poly1305_open_gather(
|
||||
const EVP_AEAD_CTX *ctx, uint8_t *out, const uint8_t *nonce,
|
||||
size_t nonce_len, const uint8_t *in, size_t in_len, const uint8_t *in_tag,
|
||||
size_t in_tag_len, const uint8_t *ad, size_t ad_len) {
|
||||
const struct aead_chacha20_poly1305_ctx *c20_ctx = ctx->aead_state;
|
||||
|
||||
if (nonce_len != 12) {
|
||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_UNSUPPORTED_NONCE_SIZE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (in_tag_len != ctx->tag_len) {
|
||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// |CRYPTO_chacha_20| uses a 32-bit block counter. Therefore we disallow
|
||||
// individual operations that work on more than 256GB at a time.
|
||||
// |in_len_64| is needed because, on 32-bit platforms, size_t is only
|
||||
// 32-bits and this produces a warning because it's always false.
|
||||
// Casting to uint64_t inside the conditional is not sufficient to stop
|
||||
// the warning.
|
||||
const uint64_t in_len_64 = in_len;
|
||||
if (in_len_64 >= (UINT64_C(1) << 32) * 64 - 64) {
|
||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
union open_data data;
|
||||
if (asm_capable()) {
|
||||
OPENSSL_memcpy(data.in.key, c20_ctx->key, 32);
|
||||
data.in.counter = 0;
|
||||
OPENSSL_memcpy(data.in.nonce, nonce, 12);
|
||||
chacha20_poly1305_open(out, in, in_len, ad, ad_len, &data);
|
||||
} else {
|
||||
calc_tag(data.out.tag, c20_ctx, nonce, ad, ad_len, in, in_len, NULL, 0);
|
||||
CRYPTO_chacha_20(out, in, in_len, c20_ctx->key, nonce, 1);
|
||||
}
|
||||
|
||||
if (CRYPTO_memcmp(data.out.tag, in_tag, ctx->tag_len) != 0) {
|
||||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const EVP_AEAD aead_chacha20_poly1305 = {
|
||||
32, // key len
|
||||
12, // nonce len
|
||||
POLY1305_TAG_LEN, // overhead
|
||||
POLY1305_TAG_LEN, // max tag length
|
||||
1, // seal_scatter_supports_extra_in
|
||||
|
||||
aead_chacha20_poly1305_init,
|
||||
NULL, // init_with_direction
|
||||
aead_chacha20_poly1305_cleanup,
|
||||
NULL /* open */,
|
||||
aead_chacha20_poly1305_seal_scatter,
|
||||
aead_chacha20_poly1305_open_gather,
|
||||
NULL, // get_iv
|
||||
NULL, // tag_len
|
||||
};
|
||||
|
||||
const EVP_AEAD *EVP_aead_chacha20_poly1305(void) {
|
||||
return &aead_chacha20_poly1305;
|
||||
}
|
||||
@@ -61,7 +61,6 @@
|
||||
#include <openssl/nid.h>
|
||||
|
||||
#include "../internal.h"
|
||||
#include "internal.h"
|
||||
|
||||
|
||||
static int null_init_key(EVP_CIPHER_CTX *ctx, const uint8_t *key,
|
||||
@@ -57,8 +57,6 @@
|
||||
#include <openssl/cipher.h>
|
||||
#include <openssl/nid.h>
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
|
||||
#define c2l(c, l) \
|
||||
do { \
|
||||
@@ -319,7 +317,7 @@ static void RC2_set_key(RC2_KEY *key, int len, const uint8_t *data, int bits) {
|
||||
unsigned int c, d;
|
||||
|
||||
k = (uint8_t *)&key->data[0];
|
||||
*k = 0; /* for if there is a zero length key */
|
||||
*k = 0; // for if there is a zero length key
|
||||
|
||||
if (len > 128) {
|
||||
len = 128;
|
||||
@@ -335,7 +333,7 @@ static void RC2_set_key(RC2_KEY *key, int len, const uint8_t *data, int bits) {
|
||||
k[i] = data[i];
|
||||
}
|
||||
|
||||
/* expand table */
|
||||
// expand table
|
||||
d = k[len - 1];
|
||||
j = 0;
|
||||
for (i = len; i < 128; i++, j++) {
|
||||
@@ -343,7 +341,7 @@ static void RC2_set_key(RC2_KEY *key, int len, const uint8_t *data, int bits) {
|
||||
k[i] = d;
|
||||
}
|
||||
|
||||
/* hmm.... key reduction to 'bits' bits */
|
||||
// hmm.... key reduction to 'bits' bits
|
||||
|
||||
j = (bits + 7) >> 3;
|
||||
i = 128 - j;
|
||||
@@ -356,7 +354,7 @@ static void RC2_set_key(RC2_KEY *key, int len, const uint8_t *data, int bits) {
|
||||
k[i] = d;
|
||||
}
|
||||
|
||||
/* copy from bytes into uint16_t's */
|
||||
// copy from bytes into uint16_t's
|
||||
ki = &(key->data[63]);
|
||||
for (i = 127; i >= 0; i -= 2) {
|
||||
*(ki--) = ((k[i] << 8) | k[i - 1]) & 0xffff;
|
||||
@@ -364,8 +362,8 @@ static void RC2_set_key(RC2_KEY *key, int len, const uint8_t *data, int bits) {
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
int key_bits; /* effective key bits */
|
||||
RC2_KEY ks; /* key schedule */
|
||||
int key_bits; // effective key bits
|
||||
RC2_KEY ks; // key schedule
|
||||
} EVP_RC2_KEY;
|
||||
|
||||
static int rc2_init_key(EVP_CIPHER_CTX *ctx, const uint8_t *key,
|
||||
@@ -401,8 +399,8 @@ static int rc2_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr) {
|
||||
key->key_bits = EVP_CIPHER_CTX_key_length(ctx) * 8;
|
||||
return 1;
|
||||
case EVP_CTRL_SET_RC2_KEY_BITS:
|
||||
/* Should be overridden by later call to |EVP_CTRL_INIT|, but
|
||||
* people call it, so it may as well work. */
|
||||
// Should be overridden by later call to |EVP_CTRL_INIT|, but
|
||||
// people call it, so it may as well work.
|
||||
key->key_bits = arg;
|
||||
return 1;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user