├── CVE-2015-3193-openssl-vs-gcrypt-modexp.c ├── CVE-2016-1938-nss-mp_div.c ├── CVE-2016-1938-nss-mp_exptmod.c ├── LICENSE ├── README.md ├── bnsqr-CVE-2014-3570-testinput.txt ├── bnsqrfuzz.c ├── gcm-ghash-fuzzing-afl.c ├── libfuzzer-kyber ├── README.md ├── build.sh └── libfuzzer-kyber.c ├── matrixssl-base-equals-modulus.c ├── matrixssl-base-zero.c ├── matrixssl-exptmod-bug-variant2.c ├── matrixssl-exptmod-bug.c ├── openssl-break-rsa-values.diff ├── openssl-vs-gcrypt-modexp.c ├── openssl-vs-matrixssl-modexp.c └── point-fuzz.c /CVE-2015-3193-openssl-vs-gcrypt-modexp.c: -------------------------------------------------------------------------------- 1 | /* Example code to show miscalculation of BN_mod_exp() function in OpenSSL (CVE-2015-3193) 2 | * 3 | * compile: 4 | * gcc -o [output] [input] -lgcrypt -lcrypto 5 | * 6 | * OpenSSL 1.0.2 versions before 1.0.2e on x86_64 contain a bug in the function BN_mod_exp(), 7 | * sometimes it produces wrong results. This example code will do a calculation that is affected 8 | * and compares the result with the same calculation done by libgcrypt. 9 | * 10 | * by Hanno Böck, license: CC0 (public domain) 11 | */ 12 | 13 | #include 14 | #include 15 | 16 | #define MI "414141414141414141414127414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005" 17 | #define AI "050505050505" 18 | #define BI "02" 19 | 20 | int main() { 21 | gcry_mpi_t ag = gcry_mpi_new(0); 22 | gcry_mpi_t bg = gcry_mpi_new(0); 23 | gcry_mpi_t mg = gcry_mpi_new(0); 24 | gcry_mpi_t rg = gcry_mpi_new(0); 25 | char* o; 26 | size_t i; 27 | BN_CTX *ctx = BN_CTX_new(); 28 | BIGNUM *a = BN_new(); 29 | BIGNUM *b = BN_new(); 30 | BIGNUM *m = BN_new(); 31 | BIGNUM *r = BN_new(); 32 | 33 | gcry_mpi_scan(&mg, GCRYMPI_FMT_HEX, MI, 0, NULL); 34 | gcry_mpi_scan(&ag, GCRYMPI_FMT_HEX, AI, 0, NULL); 35 | gcry_mpi_scan(&bg, GCRYMPI_FMT_HEX, BI, 0, NULL); 36 | gcry_mpi_powm(rg, ag, bg, mg); 37 | gcry_mpi_aprint(GCRYMPI_FMT_HEX, (unsigned char**) &o, &i, rg); 38 | printf("%s\n",o); 39 | 40 | 41 | BN_hex2bn(&m, MI); 42 | BN_hex2bn(&a, AI); 43 | BN_hex2bn(&b, BI); 44 | BN_mod_exp(r, a, b, m, ctx); 45 | printf("%s\n", BN_bn2hex(r)); 46 | 47 | if (strcmp(BN_bn2hex(r), o)!=0) printf("fail\n"); else printf("ok\n"); 48 | } 49 | -------------------------------------------------------------------------------- /CVE-2016-1938-nss-mp_div.c: -------------------------------------------------------------------------------- 1 | /* Example code for bug CVE-2016-1938 in mp_div() 2 | * author: Hanno Böck, license: CC0 / public domain 3 | * 4 | * The nss library before 3.21 contained a bug in the division 5 | * function mp_div(). On certain corner cases it will produce 6 | * wrong results. 7 | * 8 | * The mp_ functions are not part of the public API, one needs 9 | * to compile libmpi separately to test those functions. 10 | */ 11 | 12 | #include 13 | 14 | #define MP_IOFUNC 1 15 | #include 16 | 17 | void check_div(char *as, char *bs) 18 | { 19 | mp_int a, b, res1, res2, res3, res4, res5; 20 | 21 | mp_init(&a); 22 | mp_init(&b); 23 | mp_init(&res1); 24 | mp_init(&res2); 25 | mp_init(&res3); 26 | mp_init(&res4); 27 | mp_init(&res5); 28 | 29 | mp_read_radix(&a, as, 16); 30 | mp_read_radix(&b, bs, 16); 31 | 32 | mp_div(&a, &b, &res1, &res2); 33 | 34 | printf("div "); 35 | mp_print(&res1, stdout); 36 | printf("\nmod "); 37 | mp_print(&res2, stdout); 38 | printf("\n"); 39 | 40 | mp_mul(&b, &res1, &res3); 41 | 42 | mp_add(&res3, &res2, &res4); 43 | 44 | printf("This should match the original a value:\n"); 45 | mp_print(&res4, stdout); 46 | printf("\n"); 47 | 48 | mp_sub(&res4, &a, &res5); 49 | 50 | printf("This should be zero:\n"); 51 | mp_print(&res5, stdout); 52 | printf("\n\n"); 53 | 54 | mp_clear(&a); 55 | mp_clear(&b); 56 | mp_clear(&res1); 57 | mp_clear(&res2); 58 | mp_clear(&res3); 59 | mp_clear(&res4); 60 | mp_clear(&res5); 61 | 62 | } 63 | 64 | int main() 65 | { 66 | check_div("10000000000000001000000000000000000000", 67 | "10000000000000001001"); 68 | check_div 69 | ("801C4D3A9DE4691ADDBFC7D2D2DE2DA7114125A77FECE17FDA204B73FA3CDA4FF783AEE4453952BEF81DF7A9114125A700", 70 | "801C4D3A9DE4691ADDBFC7D2D2DE2DA7114125A7CEF66E9B76BAC1"); 71 | check_div 72 | ("B7B7B7B7B7B7B7B7B7B7B7939393939393939393939393939393B7B7B7B7B7B70080FFFFC1B7BAB70001B7", 73 | "B7B7B7B7B7B7B7B7B7B7C1B7BAB7DE00648B"); 74 | check_div 75 | ("BFC7D2E66986FFFCE1B4D2DEF82CBEF80000FADACE4B73F710AED25E000004001DE9BEF81DE91DE9A9556301F7A9551C", 76 | "BFC7D2E66986FFFCE1B4D2DEF82CBEF81DE9A9556301F7A9551CBFC7D2E46986FFFCE1B4D2BAC1"); 77 | 78 | return 0; 79 | } 80 | -------------------------------------------------------------------------------- /CVE-2016-1938-nss-mp_exptmod.c: -------------------------------------------------------------------------------- 1 | /* Example code for bug CVE-2016-1938 in mp_exptmod() 2 | * author: Hanno Böck, license: CC0 / public domain 3 | * 4 | * This shows that a bug in the mp_div() function of nss can also produce wrong results 5 | * in mp_exptmod(). 6 | * Two calculations are compared: Directly calling mp_exptmod() and calling mp_expt() 7 | * and mp_mod() separately. A correct implementation should always produce the same 8 | * result. 9 | */ 10 | 11 | #define MP_IOFUNC 1 12 | #include 13 | 14 | #define MI "0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0EED0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F7C000000000000000000000000000000000000000000000000000000000000000000000000000000000000" 15 | #define AI "80" 16 | #define BI "fc" 17 | 18 | int main() 19 | { 20 | mp_int an, bn, mn, r1, r2, xn; 21 | 22 | mp_init(&an); 23 | mp_init(&bn); 24 | mp_init(&mn); 25 | mp_init(&r1); 26 | mp_init(&xn); 27 | mp_init(&r2); 28 | 29 | mp_read_radix(&an, AI, 16); 30 | mp_read_radix(&bn, BI, 16); 31 | mp_read_radix(&mn, MI, 16); 32 | 33 | mp_exptmod(&an, &bn, &mn, &r2); 34 | mp_expt(&an, &bn, &xn); 35 | mp_mod(&xn, &mn, &r1); 36 | 37 | mp_print(&r1, stdout); 38 | printf("\n"); 39 | 40 | mp_print(&r2, stdout); 41 | printf("\n"); 42 | 43 | if (mp_cmp(&r1, &r2) != 0) 44 | printf("results don't match\n"); 45 | else 46 | printf("results match\n"); 47 | 48 | mp_clear(&an); 49 | mp_clear(&bn); 50 | mp_clear(&mn); 51 | mp_clear(&r1); 52 | mp_clear(&r2); 53 | mp_clear(&xn); 54 | 55 | return 0; 56 | } 57 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | CC0 1.0 Universal 2 | 3 | Statement of Purpose 4 | 5 | The laws of most jurisdictions throughout the world automatically confer 6 | exclusive Copyright and Related Rights (defined below) upon the creator and 7 | subsequent owner(s) (each and all, an "owner") of an original work of 8 | authorship and/or a database (each, a "Work"). 9 | 10 | Certain owners wish to permanently relinquish those rights to a Work for the 11 | purpose of contributing to a commons of creative, cultural and scientific 12 | works ("Commons") that the public can reliably and without fear of later 13 | claims of infringement build upon, modify, incorporate in other works, reuse 14 | and redistribute as freely as possible in any form whatsoever and for any 15 | purposes, including without limitation commercial purposes. These owners may 16 | contribute to the Commons to promote the ideal of a free culture and the 17 | further production of creative, cultural and scientific works, or to gain 18 | reputation or greater distribution for their Work in part through the use and 19 | efforts of others. 20 | 21 | For these and/or other purposes and motivations, and without any expectation 22 | of additional consideration or compensation, the person associating CC0 with a 23 | Work (the "Affirmer"), to the extent that he or she is an owner of Copyright 24 | and Related Rights in the Work, voluntarily elects to apply CC0 to the Work 25 | and publicly distribute the Work under its terms, with knowledge of his or her 26 | Copyright and Related Rights in the Work and the meaning and intended legal 27 | effect of CC0 on those rights. 28 | 29 | 1. Copyright and Related Rights. A Work made available under CC0 may be 30 | protected by copyright and related or neighboring rights ("Copyright and 31 | Related Rights"). Copyright and Related Rights include, but are not limited 32 | to, the following: 33 | 34 | i. the right to reproduce, adapt, distribute, perform, display, communicate, 35 | and translate a Work; 36 | 37 | ii. moral rights retained by the original author(s) and/or performer(s); 38 | 39 | iii. publicity and privacy rights pertaining to a person's image or likeness 40 | depicted in a Work; 41 | 42 | iv. rights protecting against unfair competition in regards to a Work, 43 | subject to the limitations in paragraph 4(a), below; 44 | 45 | v. rights protecting the extraction, dissemination, use and reuse of data in 46 | a Work; 47 | 48 | vi. database rights (such as those arising under Directive 96/9/EC of the 49 | European Parliament and of the Council of 11 March 1996 on the legal 50 | protection of databases, and under any national implementation thereof, 51 | including any amended or successor version of such directive); and 52 | 53 | vii. other similar, equivalent or corresponding rights throughout the world 54 | based on applicable law or treaty, and any national implementations thereof. 55 | 56 | 2. Waiver. To the greatest extent permitted by, but not in contravention of, 57 | applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and 58 | unconditionally waives, abandons, and surrenders all of Affirmer's Copyright 59 | and Related Rights and associated claims and causes of action, whether now 60 | known or unknown (including existing as well as future claims and causes of 61 | action), in the Work (i) in all territories worldwide, (ii) for the maximum 62 | duration provided by applicable law or treaty (including future time 63 | extensions), (iii) in any current or future medium and for any number of 64 | copies, and (iv) for any purpose whatsoever, including without limitation 65 | commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes 66 | the Waiver for the benefit of each member of the public at large and to the 67 | detriment of Affirmer's heirs and successors, fully intending that such Waiver 68 | shall not be subject to revocation, rescission, cancellation, termination, or 69 | any other legal or equitable action to disrupt the quiet enjoyment of the Work 70 | by the public as contemplated by Affirmer's express Statement of Purpose. 71 | 72 | 3. Public License Fallback. Should any part of the Waiver for any reason be 73 | judged legally invalid or ineffective under applicable law, then the Waiver 74 | shall be preserved to the maximum extent permitted taking into account 75 | Affirmer's express Statement of Purpose. In addition, to the extent the Waiver 76 | is so judged Affirmer hereby grants to each affected person a royalty-free, 77 | non transferable, non sublicensable, non exclusive, irrevocable and 78 | unconditional license to exercise Affirmer's Copyright and Related Rights in 79 | the Work (i) in all territories worldwide, (ii) for the maximum duration 80 | provided by applicable law or treaty (including future time extensions), (iii) 81 | in any current or future medium and for any number of copies, and (iv) for any 82 | purpose whatsoever, including without limitation commercial, advertising or 83 | promotional purposes (the "License"). The License shall be deemed effective as 84 | of the date CC0 was applied by Affirmer to the Work. Should any part of the 85 | License for any reason be judged legally invalid or ineffective under 86 | applicable law, such partial invalidity or ineffectiveness shall not 87 | invalidate the remainder of the License, and in such case Affirmer hereby 88 | affirms that he or she will not (i) exercise any of his or her remaining 89 | Copyright and Related Rights in the Work or (ii) assert any associated claims 90 | and causes of action with respect to the Work, in either case contrary to 91 | Affirmer's express Statement of Purpose. 92 | 93 | 4. Limitations and Disclaimers. 94 | 95 | a. No trademark or patent rights held by Affirmer are waived, abandoned, 96 | surrendered, licensed or otherwise affected by this document. 97 | 98 | b. Affirmer offers the Work as-is and makes no representations or warranties 99 | of any kind concerning the Work, express, implied, statutory or otherwise, 100 | including without limitation warranties of title, merchantability, fitness 101 | for a particular purpose, non infringement, or the absence of latent or 102 | other defects, accuracy, or the present or absence of errors, whether or not 103 | discoverable, all to the greatest extent permissible under applicable law. 104 | 105 | c. Affirmer disclaims responsibility for clearing rights of other persons 106 | that may apply to the Work or any use thereof, including without limitation 107 | any person's Copyright and Related Rights in the Work. Further, Affirmer 108 | disclaims responsibility for obtaining any necessary consents, permissions 109 | or other rights required for any use of the Work. 110 | 111 | d. Affirmer understands and acknowledges that Creative Commons is not a 112 | party to this document and has no duty or obligation with respect to this 113 | CC0 or use of the Work. 114 | 115 | For more information, please see 116 | 117 | 118 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # bignum-fuzz 2 | Code to fuzz bignum libraries 3 | 4 | 5 | CVE-2015-3193-openssl-vs-gcrypt-modexp.c 6 | 7 | This is a simple test that will do a calculation that some versions of OpenSSL will get wrong and compare the result with libgcrypt. 8 | 9 | 10 | openssl-vs-gcrypt-modexp.c 11 | 12 | This is a sample code to fuzz the BN_mod_exp() function of OpenSSL and the gcry_mpi_powm() function of libgcrypt. 13 | 14 | 15 | Usage instructions are in the code. -------------------------------------------------------------------------------- /bnsqr-CVE-2014-3570-testinput.txt: -------------------------------------------------------------------------------- 1 | Test input for CVE-2014-3570 / BN_sqr() bug in OpenSSL 2 | see https://www.openssl.org/news/secadv/20150108.txt 3 | 4 | input 5 | E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E3E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E667E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7C7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7E7 6 | 7 | correct output 8 | D2145698DB1D5FA1E42668AAED2F71B3F6387ABCFF417C86C90B4D8FD2145698DB1D5FA1E42668AAED2F71B3F6487ABCFF4183C6084A8CCF115395D81A5C9EE12365A7EA2C6EB0F33577B9FC3E80C3054789CC0E5092D517599BDE2062A4E7296BADF03274B6F93B7DC0024486C90B4D8FD2145698DB1D5CEA2C6EB0F33577B9FC3E80C3054789CC0E5092D51759A7DE2028AAED2F71B3F6387ABCFF4183C6084A8CCF115395D81B5C9EE12365A7EA2C6EB0F33577B9FC3E80C3054789CC0E5092D517599BDE2062A4E7296BADF03274B6F93B7DC0024486C90B4D8FD2145698DB1D5FA1E42668AAED2F71B3F6387ABF3F4183C6084A8CCF115395D81A5C9EDF7F3CFAB87633F1AF6D8AE8A66421DF9D5B18D694520FD4CA884603C17F3CFAB87633F5AF6D2AE8A66421DF9D5B18D694520FCD8B4906C4823FFDBB7936F4B2702DEBA96724E2A05E1BD9975512D08E4C09C7854300BE7C39F7B57330EEAC6A27E5A3611EDC9A5815D3914F0CCA884603C17F3CFAB87633F46724E2A05E1BD9975512D08E4C09C7854300BE7C39F7B5733128A66421DF9D5B18D694520FCD8B4906C4823FFDBB7936F4B2702DEBA96724E2A05E1BD9975512D08E4C09C7854300BE7C39F7B57330EEAC6A27E5A3611EDC9A5815D3914F0CCA884603C17F3CFAB87633F1AF6D2AE8A66421DF9D5B18D694520FCD8B4906C4823FFDBB7936F4B271 9 | 10 | incorrect output 11 | D2145698DB1D5FA1E42668AAED2F71B3F6387ABCFF417C86C90B4D8FD2145698DB1D5FA1E42668AAED2F71B3F6487ABCFF4183C6084A8CCF115395D81A5C9EE12365A7EA2C6EB0F33577B9FC3E80C3054789CC0E5092D517599BDE2062A4E7296BADF03274B6F93B7DC0024486C90B4D8FD2145698DB1D5CEA2C6EB0F33577B9FC3E80C3054789CC0E5092D51759A7DE2028AAED2F71B3F6387ABCFF4183C6084A8CCF115395D81B5C9EE12365A7EA2C6EB0F33577B9FC3E80C3054789CC0E5092D517599BDE2062A4E7296BADF03274B6F93B7DC0024486C90B4D8FD2145698DB1D5FA1E42668AAED2F71B3F6387ABF3F4183C6084A8CCF115395D81A5C9EDF7F3CFAB87633F1AF6D8AE8A66421DF9D5B18D694520FD4CA884603C17F3CFAB87633F5AF6D2AE8A56421DF9D5B18D694520FCD8B4906C4823FFDBB7936F4B2702DEBA96724E2A05E1BD9975512D08E4C09C7854300BE7C39F7B57330EEAC6A27E5A3611EDC9A5815D3914F0CCA884603C17F3CFAB87633F46724E2A05E1BD9975512D08E4C09C7854300BE7C39F7B5733128A66421DF9D5B18D694520FCD8B4906C4823FFDBB7936F4B2702DEBA96724E2A05E1BD9975512D08E4C09C7854300BE7C39F7B57330EEAC6A27E5A3611EDC9A5815D3914F0CCA884603C17F3CFAB87633F1AF6D2AE8A66421DF9D5B18D694520FCD8B4906C4823FFDBB7936F4B271 12 | -------------------------------------------------------------------------------- /bnsqrfuzz.c: -------------------------------------------------------------------------------- 1 | /* Fompare result of BN_sqr() and BN_mul() functions in OpenSSL 2 | * 3 | * Can be used to find the CVE-2014-3570 bug in BN_sqr(). 4 | * You need to link against a version of libcrypto compiled with american fuzzy lop. 5 | * 6 | * License: CC0 / public domain 7 | * Author: Hanno Böck, https://hboeck.de/ 8 | */ 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | #define MAXLEN 500 15 | 16 | int main(int argc, char *argv[]) 17 | { 18 | size_t len; 19 | unsigned char in[MAXLEN]; 20 | BN_CTX *ctx = BN_CTX_new(); 21 | BIGNUM *x = BN_new(); 22 | BIGNUM *r = BN_new(); 23 | 24 | if (argc != 2) { 25 | printf("no file given\n"); 26 | return -1; 27 | } 28 | FILE *f = fopen(argv[1], "rb"); 29 | if (!f) { 30 | printf("can't open file\n"); 31 | return -1; 32 | } 33 | 34 | len = fread(in, sizeof(char), MAXLEN, f); 35 | fclose(f); 36 | 37 | 38 | BN_bin2bn(in, len, x); 39 | 40 | BN_sqr(r, x, ctx); 41 | BN_mul(x, x, x, ctx); 42 | 43 | BN_print_fp(stdout, r); 44 | printf("\n"); 45 | BN_print_fp(stdout, x); 46 | printf("\n"); 47 | 48 | assert(BN_cmp(r, x) == 0); 49 | 50 | BN_free(x); 51 | BN_free(r); 52 | BN_CTX_free(ctx); 53 | 54 | return 0; 55 | 56 | } 57 | -------------------------------------------------------------------------------- /gcm-ghash-fuzzing-afl.c: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | for matrixssl vs openssl: 4 | afl-clang-fast gcm2.c -I /mnt/ram/matrixssl-3-8-3-open/ -lssl -lcrypto 5 | afl-clang-fast/libcrypt_s.a afl-clang-fast/libcore_s.a 6 | 7 | for openssl vs. nss: 8 | gcc -g gcm.c -lcrypto -fsanitize=address -I/usr/include/nspr -I/usr/include/nss 9 | /usr/lib/libfreebl.a /usr/lib/libnspr4.so /usr/lib/libnssutil3.so -Wall 10 | -pedantic 11 | 12 | afl-gcc -O2 gcm.c -o gcm libcrypto.a libfreebl.a libnspr4.a -I/usr/include/nspr 13 | -I/usr/include/nss -lpthread -ldl /usr/lib/libnssutil3.so 14 | */ 15 | 16 | //#define NO_OPENSSL 1 17 | //#define NO_GCRYPT 1 18 | #define NO_NSS 1 19 | #define NO_MBED 1 20 | #define NO_MATRIX 1 21 | #define NO_CYCLONE 1 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | #include 29 | 30 | #ifndef NO_NSS 31 | #include 32 | #include 33 | #endif 34 | 35 | #ifndef NO_MBED 36 | #include 37 | #endif 38 | 39 | /* matrixssl */ 40 | #ifndef NO_MATRIX 41 | #include 42 | #endif 43 | 44 | #ifndef NO_CYCLONE 45 | #include 46 | #include 47 | #endif 48 | 49 | #ifndef NO_GCRYPT 50 | #include 51 | #endif 52 | 53 | #define KEYLEN 16 /* 16 = 128 bit */ 54 | #define IVLEN 12 /* 12 = 96 bit, default */ 55 | #define TAGLEN 16 56 | 57 | int main(int argc, char **argv) { 58 | FILE *f; 59 | unsigned char buf[4096]; 60 | unsigned char enc[8192]; 61 | unsigned char tag[16]; 62 | unsigned char *key; 63 | unsigned char *iv; 64 | unsigned char *input; 65 | unsigned char mout[4096]; 66 | unsigned char mtag[16]; 67 | unsigned char gcrypttag[16]; 68 | size_t s; 69 | int i, j; 70 | unsigned int u; 71 | EVP_CIPHER_CTX *ctx; 72 | #ifndef NO_NSS 73 | AESContext *ac; 74 | CK_GCM_PARAMS gcmparams; 75 | unsigned char *params; 76 | #endif 77 | unsigned char *empty = (unsigned char *)""; 78 | #ifndef NO_MBED 79 | mbedtls_gcm_context mgcm; 80 | #endif 81 | #ifndef NO_MATRIX 82 | psAesGcm_t mactx; 83 | unsigned char *somebuf; 84 | unsigned char matrixtag[16]; 85 | #endif 86 | #ifndef NO_CYCLONE 87 | AesContext aesc; 88 | unsigned char cyclonetag[16]; 89 | #endif 90 | #ifndef NO_GCRYPT 91 | gcry_cipher_hd_t gcipher; 92 | #endif 93 | 94 | if (argc < 2) { 95 | printf("No file given\n"); 96 | return 1; 97 | } 98 | f = fopen(argv[1], "rb"); 99 | s = fread(buf, 1, 4096, f); 100 | 101 | if (s < KEYLEN + IVLEN + 1) 102 | return -1; 103 | s -= KEYLEN + IVLEN; 104 | key = buf; 105 | iv = buf + KEYLEN; 106 | input = buf + KEYLEN + IVLEN; 107 | 108 | #ifndef NO_CYCLONE 109 | /* CycloneCrypto */ 110 | aesInit(&aesc, key, KEYLEN); 111 | gcmEncrypt(&aesCipherAlgo, &aesc, iv, IVLEN, input, s, empty, buf, 0, 112 | cyclonetag, TAGLEN); 113 | for (i = 0; i < 16; i++) 114 | printf("%02x:", cyclonetag[i]); 115 | printf("\n"); 116 | #endif 117 | 118 | #ifndef NO_MATRIX 119 | /* matrixssl */ 120 | psAesInitGCM(&mactx, key, KEYLEN); 121 | psAesReadyGCM(&mactx, iv, input, s); 122 | psAesEncryptGCM(&mactx, empty, somebuf, 0); 123 | psAesGetGCMTag(&mactx, 16, matrixtag); 124 | for (i = 0; i < 16; i++) 125 | printf("%02x:", matrixtag[i]); 126 | printf("\n"); 127 | #endif 128 | 129 | #ifndef NO_MBED 130 | /* mbedtls */ 131 | mbedtls_gcm_init(&mgcm); 132 | mbedtls_gcm_setkey(&mgcm, MBEDTLS_CIPHER_ID_AES, key, 128); 133 | mbedtls_gcm_crypt_and_tag(&mgcm, MBEDTLS_GCM_ENCRYPT, 0, iv, IVLEN, input, s, 134 | empty, mout, 16, mtag); 135 | mbedtls_gcm_free(&mgcm); 136 | for (i = 0; i < 16; i++) 137 | printf("%02x:", mtag[i]); 138 | printf("\n"); 139 | #endif 140 | 141 | #ifndef NO_GCRYPT 142 | gcry_cipher_open(&gcipher, GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_GCM, 0); 143 | gcry_cipher_setkey(gcipher, buf, KEYLEN); 144 | gcry_cipher_setiv(gcipher, buf + KEYLEN, IVLEN); 145 | gcry_cipher_authenticate(gcipher, buf + KEYLEN + IVLEN, s); 146 | gcry_cipher_gettag(gcipher, gcrypttag, 16); 147 | for (j = 0; j < 16; j++) 148 | printf("%02x:", gcrypttag[j]); 149 | printf("\n"); 150 | #endif 151 | 152 | #ifndef NO_OPENSSL 153 | ctx = EVP_CIPHER_CTX_new(); 154 | EVP_EncryptInit_ex(ctx, EVP_aes_128_gcm(), 0, 0, 0); 155 | /* EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, IVLEN, 0); */ /* only 156 | needed if 157 | != 12 */ 158 | EVP_EncryptInit_ex(ctx, 0, 0, buf, buf + KEYLEN); 159 | EVP_EncryptUpdate(ctx, 0, &i, buf + KEYLEN + IVLEN, s); 160 | EVP_EncryptFinal_ex(ctx, empty, &i); 161 | EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, 16, tag); 162 | EVP_CIPHER_CTX_free(ctx); 163 | for (i = 0; i < 16; i++) 164 | printf("%02x:", tag[i]); 165 | printf("\n"); 166 | #endif 167 | 168 | #ifndef NO_NSS 169 | gcmparams.pIv = buf + KEYLEN; 170 | gcmparams.ulIvLen = IVLEN; 171 | gcmparams.pAAD = buf + KEYLEN + IVLEN; 172 | gcmparams.ulAADLen = s; 173 | gcmparams.ulTagBits = 16 * 8; 174 | params = (unsigned char *)&gcmparams; 175 | ac = AES_CreateContext(buf, params, NSS_AES_GCM, 1, KEYLEN, 16); 176 | AES_Encrypt(ac, enc, &u, 8192, empty, 0); 177 | for (j = 0; j < u; j++) 178 | printf("%02x:", enc[j]); 179 | printf("\n"); 180 | #endif 181 | 182 | assert(memcmp(gcrypttag, tag, 16) == 0); 183 | 184 | return 0; 185 | } 186 | -------------------------------------------------------------------------------- /libfuzzer-kyber/README.md: -------------------------------------------------------------------------------- 1 | libfuzzer-kyber 2 | =============== 3 | 4 | libfuzzer stub for the kyber post quantum kem algorithm. 5 | 6 | description 7 | =========== 8 | 9 | The stub code will run the indcpa_enc function of kyber both with the reference and the avx2 10 | implementation and will compare the result. It will throw an assert if they don't match. 11 | 12 | usage 13 | ===== 14 | 15 | Run: 16 | ./build.sh fetch 17 | 18 | It will fetch kyber from github, get libFuzzer.a and create a fuzzer stub libfuzzer-kyber. 19 | All functions in the reference implementation of kyber will be prefixed with ref_. 20 | 21 | If you want to rebuild without re-fetching kyber and libFuzzer just run: 22 | ./build.sh 23 | -------------------------------------------------------------------------------- /libfuzzer-kyber/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if [ "$1" = "fetch" ]; then 4 | git clone --depth=1 https://github.com/pq-crystals/kyber.git 5 | sed -e 's:polyvec_:ref_polyvec_:g' -e 's:poly_:ref_poly_:g' \ 6 | -e 's:omegas_:ref_omegas_:g' \ 7 | -e 's:indcpa_:ref_indcpa_:g' \ 8 | -e 's:crypto_:ref_crypto_:g' \ 9 | -e 's:kyber_:ref_kyber_:g' \ 10 | -e 's:psis_:ref_psis_:g' \ 11 | -e 's:montgomery_reduce:ref_montgomery_reduce:g' \ 12 | -e 's:barrett_reduce:ref_barrett_reduce:g' \ 13 | -e 's:freeze:ref_freeze:g' \ 14 | -e 's:gen_matrix:ref_gen_matrix:g' \ 15 | -e 's: pack_: ref_pack_:g' \ 16 | -e 's: unpack_: ref_unpack_:g' \ 17 | -e 's:shake:ref_shake:g' \ 18 | -e 's:keccak:ref_keccak:g' \ 19 | -e 's:Keccak:ref_Keccak:g' \ 20 | -e 's:sha3:ref_sha3:g' \ 21 | -e 's:verify(:ref_verify\(:g' \ 22 | -e 's: ntt(: ref_ntt\(:g' \ 23 | -e 's: invntt(: ref_invntt\(:g' \ 24 | -e 's: cbd(: ref_cbd\(:g' \ 25 | -e 's: cmov(: ref_cmov\(:g' \ 26 | -e 's: load64(: ref_load64(:g' \ 27 | -e 's: store64(: ref_store64(:g' \ 28 | -e 's: randombytes(: ref_randombytes(:g' \ 29 | -e 's: cpucycles(: ref_cpucycles(:g' \ 30 | kyber/ref/*.c kyber/ref/*.h -i 31 | fi 32 | 33 | CFLAGS="-march=native -fsanitize=address -fsanitize-coverage=trace-pc-guard" 34 | 35 | pushd kyber/ref 36 | clang $CFLAGS -c cbd.c cpucycles.c fips202.c indcpa.c kem.c kex.c ntt.c poly.c polyvec.c precomp.c randombytes.c reduce.c verify.c 37 | popd 38 | 39 | pushd kyber/avx2 40 | clang $CFLAGS -c cbdref.c consts.c cpucycles.c fips202.c fips202x4.c genmatrix.c indcpa.c keccak4x/KeccakP-1600-times4-SIMD256.c kem.c kex.c poly.c polyvec.c precomp.c randombytes.c reduce.c verify.c 41 | popd 42 | 43 | clang -fsanitize-coverage=trace-pc-guard -fsanitize=address libfuzzer-kyber.c -c 44 | clang++ libfuzzer-kyber.o kyber/*/*.o libFuzzer.a -fsanitize=address -fsanitize-coverage=trace-pc-guard kyber/*/*.s -o libfuzzer-kyber 45 | -------------------------------------------------------------------------------- /libfuzzer-kyber/libfuzzer-kyber.c: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Expected input size: 1152 (additional content in larger files will be ignored) 4 | 5 | */ 6 | 7 | #include "kyber/ref/params.h" 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | void indcpa_enc(unsigned char *c, const unsigned char *m, 15 | const unsigned char *pk, const unsigned char *coins); 16 | 17 | void ref_indcpa_enc(unsigned char *c, const unsigned char *m, 18 | const unsigned char *pk, const unsigned char *coins); 19 | 20 | int LLVMFuzzerTestOneInput(const uint8_t * datax, size_t size) 21 | { 22 | 23 | unsigned char out1[KYBER_INDCPA_BYTES]; 24 | unsigned char out2[KYBER_INDCPA_BYTES]; 25 | int i; 26 | 27 | unsigned char *data = (unsigned char *)datax; 28 | 29 | if (size < 30 | KYBER_INDCPA_MSGBYTES + KYBER_INDCPA_PUBLICKEYBYTES + 31 | KYBER_SYMBYTES) 32 | return 0; 33 | 34 | indcpa_enc(out1, &data[0], &data[KYBER_INDCPA_MSGBYTES], 35 | &data[KYBER_INDCPA_MSGBYTES + KYBER_INDCPA_PUBLICKEYBYTES]); 36 | ref_indcpa_enc(out2, &data[0], &data[KYBER_INDCPA_MSGBYTES], 37 | &data[KYBER_INDCPA_MSGBYTES + 38 | KYBER_INDCPA_PUBLICKEYBYTES]); 39 | 40 | #ifdef DEBUG 41 | for (i = 0; i < KYBER_INDCPA_BYTES; i++) { 42 | printf("%02x:", out1[i]); 43 | } 44 | printf("\n"); 45 | for (i = 0; i < KYBER_INDCPA_BYTES; i++) { 46 | printf("%02x:", out2[i]); 47 | } 48 | printf("\n"); 49 | #endif 50 | 51 | assert(memcmp(out1, out2, KYBER_INDCPA_BYTES) == 0); 52 | 53 | return 0; 54 | } 55 | -------------------------------------------------------------------------------- /matrixssl-base-equals-modulus.c: -------------------------------------------------------------------------------- 1 | /* Testing MatrixSSL's pstm_exptmod with base == modulus 2 | * by Hanno Böck, license: CC0 3 | */ 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | unsigned char a1[] = { 11 | 0xcc 12 | }; 13 | 14 | unsigned int a1_len = 1; 15 | 16 | unsigned char b1[] = { 17 | 0xbb 18 | }; 19 | 20 | unsigned int b1_len = 1; 21 | 22 | unsigned char m1[] = { 23 | 0xcc 24 | }; 25 | 26 | unsigned int m1_len = 1; 27 | 28 | char *matrixtest(unsigned char *a_raw, int a_len, unsigned char *b_raw, 29 | int b_len, unsigned char *m_raw, int m_len) 30 | { 31 | unsigned char *rr = malloc(4096); 32 | char *buf, *buf_ptr; 33 | int i, s; 34 | pstm_int a, b, m, r; 35 | 36 | if (pstm_init_for_read_unsigned_bin(NULL, &a, a_len) < 0) { 37 | printf("pstm_init_for_read_unsigned_bin a error\n"); 38 | return 0; 39 | } 40 | if (pstm_read_unsigned_bin(&a, a_raw, a_len) != 0) { 41 | printf("pstm_read_unsigned_bin a error\n"); 42 | return 0; 43 | } 44 | if (pstm_init_for_read_unsigned_bin(NULL, &b, b_len) < 0) { 45 | printf("pstm_init_for_read_unsigned_bin b error\n"); 46 | return 0; 47 | } 48 | if (pstm_read_unsigned_bin(&b, b_raw, b_len) != 0) { 49 | printf("pstm_read_unsigned_bin b error\n"); 50 | return 0; 51 | } 52 | if (pstm_init_for_read_unsigned_bin(NULL, &m, m_len) < 0) { 53 | printf("pstm_init_for_read_unsigned_bin c error\n"); 54 | return 0; 55 | } 56 | if (pstm_read_unsigned_bin(&m, m_raw, m_len) != 0) { 57 | printf("pstm_read_unsigned_bin c error\n"); 58 | return 0; 59 | } 60 | 61 | if (pstm_init(NULL, &r) != 0) { 62 | printf("pstm_init r error\n"); 63 | return 0; 64 | } 65 | 66 | if (pstm_exptmod(NULL, &a, &b, &m, &r) != 0) { 67 | printf("pstm_exptmod error\n"); 68 | return 0; 69 | } 70 | 71 | if (pstm_to_unsigned_bin(0, &r, rr) < 0) { 72 | printf("pstm_to_unsigned_bin error\n"); 73 | return 0; 74 | } 75 | s = pstm_unsigned_bin_size(&r); 76 | buf = buf_ptr = malloc(s * 2 + 1); 77 | for (i = 0; i < s; i++) { 78 | buf_ptr += sprintf(buf_ptr, "%02X", rr[i]); 79 | } 80 | 81 | printf("matrixssl:\n%s\n", buf); 82 | return buf; 83 | } 84 | 85 | int main(int argc, char *argv[]) 86 | { 87 | matrixtest(a1, a1_len, b1, b1_len, m1, m1_len); 88 | 89 | } 90 | -------------------------------------------------------------------------------- /matrixssl-base-zero.c: -------------------------------------------------------------------------------- 1 | /* Testing MatrixSSL's pstm_exptmod with base zero 2 | * by Hanno Böck, license: CC0 3 | */ 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | unsigned char a1[] = { 10 | 0x0 11 | }; 12 | 13 | unsigned int a1_len = 1; 14 | 15 | unsigned char b1[] = { 16 | 0xaa 17 | }; 18 | 19 | unsigned int b1_len = 1; 20 | 21 | unsigned char m1[] = { 22 | 0xbb 23 | }; 24 | 25 | unsigned int m1_len = 1; 26 | 27 | char *matrixtest(unsigned char *a_raw, int a_len, unsigned char *b_raw, 28 | int b_len, unsigned char *m_raw, int m_len) 29 | { 30 | unsigned char *rr = malloc(4096); 31 | char *buf, *buf_ptr; 32 | int i, s; 33 | pstm_int a, b, m, r; 34 | 35 | if (pstm_init_for_read_unsigned_bin(NULL, &a, a_len) < 0) { 36 | printf("pstm_init_for_read_unsigned_bin a error\n"); 37 | return 0; 38 | } 39 | if (pstm_read_unsigned_bin(&a, a_raw, a_len) != 0) { 40 | printf("pstm_read_unsigned_bin a error\n"); 41 | return 0; 42 | } 43 | if (pstm_init_for_read_unsigned_bin(NULL, &b, b_len) < 0) { 44 | printf("pstm_init_for_read_unsigned_bin b error\n"); 45 | return 0; 46 | } 47 | if (pstm_read_unsigned_bin(&b, b_raw, b_len) != 0) { 48 | printf("pstm_read_unsigned_bin b error\n"); 49 | return 0; 50 | } 51 | if (pstm_init_for_read_unsigned_bin(NULL, &m, m_len) < 0) { 52 | printf("pstm_init_for_read_unsigned_bin c error\n"); 53 | return 0; 54 | } 55 | if (pstm_read_unsigned_bin(&m, m_raw, m_len) != 0) { 56 | printf("pstm_read_unsigned_bin c error\n"); 57 | return 0; 58 | } 59 | 60 | if (pstm_init(NULL, &r) != 0) { 61 | printf("pstm_init r error\n"); 62 | return 0; 63 | } 64 | 65 | if (pstm_exptmod(NULL, &a, &b, &m, &r) != 0) { 66 | printf("pstm_exptmod error\n"); 67 | return 0; 68 | } 69 | 70 | if (pstm_to_unsigned_bin(0, &r, rr) < 0) { 71 | printf("pstm_to_unsigned_bin error\n"); 72 | return 0; 73 | } 74 | s = pstm_unsigned_bin_size(&r); 75 | buf = buf_ptr = malloc(s * 2 + 1); 76 | for (i = 0; i < s; i++) { 77 | buf_ptr += sprintf(buf_ptr, "%02X", rr[i]); 78 | } 79 | 80 | printf("matrixssl:\n%s\n", buf); 81 | return buf; 82 | } 83 | 84 | int main(int argc, char *argv[]) 85 | { 86 | matrixtest(a1, a1_len, b1, b1_len, m1, m1_len); 87 | 88 | } 89 | -------------------------------------------------------------------------------- /matrixssl-exptmod-bug-variant2.c: -------------------------------------------------------------------------------- 1 | /* MatrixSSL miscalculation bug 2 | * demonstrating incomplete fix for Use CVE-2016-6887 3 | * 4 | * by Hanno Böck, license: CC0 / public domain 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | unsigned char a1[] = { 13 | 0xe7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 14 | 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 15 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 16 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 17 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 18 | 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 19 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 20 | 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 21 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xff, 22 | 0xff, 0xff, 0xe1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x14, 0x00, 23 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 24 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 25 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 26 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 27 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 28 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 29 | 0xb7, 0xcc, 0x03, 0x00, 0x00 30 | }; 31 | 32 | unsigned int a1_len = 197; 33 | 34 | unsigned char b1[] = { 35 | 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 36 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 37 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 38 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 39 | 0x00, 0x00 40 | }; 41 | 42 | unsigned int b1_len = 50; 43 | 44 | unsigned char m1[] = { 45 | 0xe7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 46 | 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 47 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 48 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 49 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xb9, 0x6c, 0x00, 50 | 0x00, 0x00, 0x00, 0xff 51 | }; 52 | 53 | unsigned int m1_len = 64; 54 | 55 | /* test bn functions from openssl/libcrypto */ 56 | char *bntest(unsigned char *a_raw, int a_len, unsigned char *b_raw, int b_len, 57 | unsigned char *m_raw, int m_len) 58 | { 59 | BN_CTX *bctx = BN_CTX_new(); 60 | BIGNUM *a = BN_new(); 61 | BIGNUM *b = BN_new(); 62 | BIGNUM *m = BN_new(); 63 | BIGNUM *res1 = BN_new(); 64 | char *result; 65 | 66 | BN_bin2bn(a_raw, a_len, a); 67 | BN_bin2bn(b_raw, b_len, b); 68 | BN_bin2bn(m_raw, m_len, m); 69 | 70 | BN_mod_exp(res1, a, b, m, bctx); 71 | result = BN_bn2hex(res1); 72 | printf("openssl:\n%s\n", result); 73 | 74 | BN_free(a); 75 | BN_free(b); 76 | BN_free(m); 77 | BN_free(res1); 78 | BN_CTX_free(bctx); 79 | 80 | return result; 81 | } 82 | 83 | char *matrixtest(unsigned char *a_raw, int a_len, unsigned char *b_raw, 84 | int b_len, unsigned char *m_raw, int m_len) 85 | { 86 | unsigned char *rr = malloc(4096); 87 | char *buf, *buf_ptr; 88 | int i, s; 89 | pstm_int a, b, m, r; 90 | 91 | if (pstm_init_for_read_unsigned_bin(NULL, &a, a_len) < 0) { 92 | printf("pstm_init_for_read_unsigned_bin a error\n"); 93 | return 0; 94 | } 95 | if (pstm_read_unsigned_bin(&a, a_raw, a_len) != 0) { 96 | printf("pstm_read_unsigned_bin a error\n"); 97 | return 0; 98 | } 99 | if (pstm_init_for_read_unsigned_bin(NULL, &b, b_len) < 0) { 100 | printf("pstm_init_for_read_unsigned_bin b error\n"); 101 | return 0; 102 | } 103 | if (pstm_read_unsigned_bin(&b, b_raw, b_len) != 0) { 104 | printf("pstm_read_unsigned_bin b error\n"); 105 | return 0; 106 | } 107 | if (pstm_init_for_read_unsigned_bin(NULL, &m, m_len) < 0) { 108 | printf("pstm_init_for_read_unsigned_bin c error\n"); 109 | return 0; 110 | } 111 | if (pstm_read_unsigned_bin(&m, m_raw, m_len) != 0) { 112 | printf("pstm_read_unsigned_bin c error\n"); 113 | return 0; 114 | } 115 | 116 | if (pstm_init(NULL, &r) != 0) { 117 | printf("pstm_init r error\n"); 118 | return 0; 119 | } 120 | 121 | if (pstm_exptmod(NULL, &a, &b, &m, &r) != 0) { 122 | printf("pstm_exptmod error\n"); 123 | return 0; 124 | } 125 | 126 | if (pstm_to_unsigned_bin(0, &r, rr) < 0) { 127 | printf("pstm_to_unsigned_bin error\n"); 128 | return 0; 129 | } 130 | s = pstm_unsigned_bin_size(&r); 131 | buf = buf_ptr = malloc(s * 2 + 1); 132 | for (i = 0; i < s; i++) { 133 | buf_ptr += sprintf(buf_ptr, "%02X", rr[i]); 134 | } 135 | 136 | printf("matrixssl:\n%s\n", buf); 137 | return buf; 138 | } 139 | 140 | int main(int argc, char *argv[]) 141 | { 142 | char *r1, *r2; 143 | 144 | r1 = matrixtest(a1, a1_len, b1, b1_len, m1, m1_len); 145 | 146 | r2 = bntest(a1, a1_len, b1, b1_len, m1, m1_len); 147 | 148 | if (strcmp(r1, r2) != 0) 149 | printf("Results differ!\n"); 150 | 151 | return 0; 152 | } 153 | -------------------------------------------------------------------------------- /matrixssl-exptmod-bug.c: -------------------------------------------------------------------------------- 1 | /* Testing MatrixSSL's pstm_exptmod with values causing a wrong result 2 | * by Hanno Böck, license: CC0 3 | */ 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | unsigned char a1[] = { 11 | 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 12 | 0x2f, 0x2f, 0x2f, 0x2f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 13 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdf, 0xff, 0x00, 14 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 15 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 16 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0xc7, 0x00, 17 | 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 18 | 0x00, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 19 | 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2d, 0x2f, 0x2f, 0x2f, 0x2f, 20 | 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x38, 0x2f, 0x2f, 0x2f, 21 | 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 22 | 0x2f, 0x3e, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x3d, 0x2f, 23 | 0x2f, 0xff, 0xff, 0xff, 0x7f, 0x2f, 0x2f, 0x28, 0x2f, 0x2f 24 | }; 25 | 26 | unsigned int a1_len = 154; 27 | 28 | unsigned char b1[] = { 29 | 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 30 | 0x32, 0x2f, 0x2f, 0x2f 31 | }; 32 | 33 | unsigned int b1_len = 16; 34 | 35 | unsigned char m1[] = { 36 | 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 37 | 0x2f, 0x2f, 0x2f, 0x2f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 38 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2f, 0x2f, 0x2f, 0x2f, 39 | 0x00, 0x00, 0x00, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 40 | 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x00, 0x00, 0x00, 0x00, 0x00, 41 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfd, 0xff, 0xff, 0xff, 0x00, 0x2f, 42 | 0x2f, 0x2f, 0x2f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 43 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x13, 44 | 0xc4, 0xbb, 0x83, 0x59, 0x00, 0x06, 0xe0, 0x77, 0xaa, 0x2f, 0x2f, 0x2f, 45 | 0x2f, 0x2f, 0x22, 0x2f, 0x2f 46 | }; 47 | 48 | unsigned int m1_len = 113; 49 | 50 | /* test bn functions from openssl/libcrypto */ 51 | char *bntest(unsigned char *a_raw, int a_len, unsigned char *b_raw, int b_len, 52 | unsigned char *m_raw, int m_len) 53 | { 54 | BN_CTX *bctx = BN_CTX_new(); 55 | BIGNUM *a = BN_new(); 56 | BIGNUM *b = BN_new(); 57 | BIGNUM *m = BN_new(); 58 | BIGNUM *res1 = BN_new(); 59 | char *result; 60 | 61 | BN_bin2bn(a_raw, a_len, a); 62 | BN_bin2bn(b_raw, b_len, b); 63 | BN_bin2bn(m_raw, m_len, m); 64 | 65 | BN_mod_exp(res1, a, b, m, bctx); 66 | printf("a: %s\n",BN_bn2hex(a)); 67 | printf("b: %s\n",BN_bn2hex(b)); 68 | printf("m: %s\n",BN_bn2hex(m)); 69 | result = BN_bn2hex(res1); 70 | printf("openssl:\n%s\n", result); 71 | 72 | BN_free(a); 73 | BN_free(b); 74 | BN_free(m); 75 | BN_free(res1); 76 | BN_CTX_free(bctx); 77 | 78 | return result; 79 | } 80 | 81 | char *matrixtest(unsigned char *a_raw, int a_len, unsigned char *b_raw, 82 | int b_len, unsigned char *m_raw, int m_len) 83 | { 84 | unsigned char *rr = malloc(4096); 85 | char *buf, *buf_ptr; 86 | int i, s; 87 | pstm_int a, b, m, r; 88 | 89 | if (pstm_init_for_read_unsigned_bin(NULL, &a, a_len) < 0) { 90 | printf("pstm_init_for_read_unsigned_bin a error\n"); 91 | return 0; 92 | } 93 | if (pstm_read_unsigned_bin(&a, a_raw, a_len) != 0) { 94 | printf("pstm_read_unsigned_bin a error\n"); 95 | return 0; 96 | } 97 | if (pstm_init_for_read_unsigned_bin(NULL, &b, b_len) < 0) { 98 | printf("pstm_init_for_read_unsigned_bin b error\n"); 99 | return 0; 100 | } 101 | if (pstm_read_unsigned_bin(&b, b_raw, b_len) != 0) { 102 | printf("pstm_read_unsigned_bin b error\n"); 103 | return 0; 104 | } 105 | if (pstm_init_for_read_unsigned_bin(NULL, &m, m_len) < 0) { 106 | printf("pstm_init_for_read_unsigned_bin c error\n"); 107 | return 0; 108 | } 109 | if (pstm_read_unsigned_bin(&m, m_raw, m_len) != 0) { 110 | printf("pstm_read_unsigned_bin c error\n"); 111 | return 0; 112 | } 113 | 114 | if (pstm_init(NULL, &r) != 0) { 115 | printf("pstm_init r error\n"); 116 | return 0; 117 | } 118 | 119 | if (pstm_exptmod(NULL, &a, &b, &m, &r) != 0) { 120 | printf("pstm_exptmod error\n"); 121 | return 0; 122 | } 123 | 124 | if (pstm_to_unsigned_bin(0, &r, rr) < 0) { 125 | printf("pstm_to_unsigned_bin error\n"); 126 | return 0; 127 | } 128 | s = pstm_unsigned_bin_size(&r); 129 | buf = buf_ptr = malloc(s * 2 + 1); 130 | for (i = 0; i < s; i++) { 131 | buf_ptr += sprintf(buf_ptr, "%02X", rr[i]); 132 | } 133 | 134 | printf("matrixssl:\n%s\n", buf); 135 | return buf; 136 | } 137 | 138 | int main(int argc, char *argv[]) 139 | { 140 | char *r1, *r2; 141 | 142 | r1 = matrixtest(a1, a1_len, b1, b1_len, m1, m1_len); 143 | 144 | r2 = bntest(a1, a1_len, b1, b1_len, m1, m1_len); 145 | 146 | if (strcmp(r1, r2) != 0) 147 | printf("Results differ!\n"); 148 | 149 | return 0; 150 | } 151 | -------------------------------------------------------------------------------- /openssl-break-rsa-values.diff: -------------------------------------------------------------------------------- 1 | This patch allows one to send malformed RSA encryptions during the handshake. 2 | One can either send zeros or the RSA key modulus. Both trigger a bug in 3 | MatrixSSL 3.8.3. 4 | Test: 5 | RSA_BREAK_ZERO=1 apps/openssl s_client -connect [host]:[port] -cipher RSA 6 | RSA_BREAK_MODULUS=1 apps/openssl s_client -connect [host]:[port] -cipher RSA 7 | 8 | --- openssl-1.0.2h-vanilla/ssl/s3_clnt.c 2016-05-03 15:44:42.000000000 +0200 9 | +++ openssl-1.0.2h/ssl/s3_clnt.c 2016-07-04 22:09:46.610230998 +0200 10 | @@ -2535,6 +2535,10 @@ 11 | if (s->options & SSL_OP_PKCS1_CHECK_2) 12 | tmp_buf[0] = 0x70; 13 | # endif 14 | + if (getenv("RSA_BREAK_ZERO")) 15 | + bzero(p, RSA_size(rsa)); 16 | + else if (getenv("RSA_BREAK_MODULUS")) 17 | + BN_bn2bin(rsa->n, p); 18 | if (n <= 0) { 19 | SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, 20 | SSL_R_BAD_RSA_ENCRYPT); 21 | -------------------------------------------------------------------------------- /openssl-vs-gcrypt-modexp.c: -------------------------------------------------------------------------------- 1 | /* Fuzz-compare the OpenSSL function BN_mod_exp() and the libgcrypt function gcry_mpi_powm(). 2 | * 3 | * To use this you should compile both libgcrypt and openssl with american fuzzy lop and then statically link everything together, e.g.: 4 | * afl-clang-fast -o [output] [input] libgcrypt.a libcrypto.a -lgpg-error 5 | * 6 | * Input is a binary file, the first bytes will decide how the rest of the file will be split into three bignums. 7 | * 8 | * by Hanno Böck, license CC0 (public domain) 9 | */ 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #define MAXBUF 1000000 19 | 20 | 21 | struct big_results { 22 | char *name; 23 | char *a; 24 | char *b; 25 | char *c; 26 | char *exptmod; 27 | }; 28 | 29 | void printres(struct big_results *res) { 30 | printf("\n%s:\n", res->name); 31 | printf("a: %s\n", res->a); 32 | printf("b: %s\n", res->b); 33 | printf("c: %s\n", res->c); 34 | printf("b^c mod a: %s\n", res->exptmod); 35 | } 36 | 37 | void freeres(struct big_results *res) { 38 | free(res->a); 39 | free(res->b); 40 | free(res->c); 41 | free(res->exptmod); 42 | } 43 | 44 | 45 | char *gcrytostring(gcry_mpi_t in) { 46 | char *a, *b; 47 | size_t i; 48 | size_t j=0; 49 | gcry_mpi_aprint(GCRYMPI_FMT_HEX, (unsigned char**) &a, &i, in); 50 | while(a[j]=='0' && j<(i-2)) j++; 51 | if ((j%2)==1) j--; 52 | if (strncmp(&a[j],"00",2)==0) j++; 53 | b=malloc(i-j); 54 | strcpy(b, &a[j]); 55 | free(a); 56 | return b; 57 | } 58 | 59 | /* test gcry functions from libgcrypt */ 60 | void gcrytest(unsigned char* a_raw, int a_len, unsigned char* b_raw, int b_len, unsigned char* c_raw, int c_len, struct big_results *res) { 61 | gcry_mpi_t a, b, c, res1, res2; 62 | 63 | /* unknown leak here */ 64 | gcry_mpi_scan(&a, GCRYMPI_FMT_USG, a_raw, a_len, NULL); 65 | res->a = gcrytostring(a); 66 | 67 | gcry_mpi_scan(&b, GCRYMPI_FMT_USG, b_raw, b_len, NULL); 68 | res->b = gcrytostring(b); 69 | 70 | gcry_mpi_scan(&c, GCRYMPI_FMT_USG, c_raw, c_len, NULL); 71 | res->c = gcrytostring(c); 72 | 73 | res1=gcry_mpi_new(0); 74 | 75 | gcry_mpi_powm(res1, b, c, a); 76 | res->exptmod=gcrytostring(res1); 77 | 78 | gcry_mpi_release(a); 79 | gcry_mpi_release(b); 80 | gcry_mpi_release(c); 81 | gcry_mpi_release(res1); 82 | } 83 | 84 | /* test bn functions from openssl/libcrypto */ 85 | void bntest(unsigned char* a_raw, int a_len, unsigned char* b_raw, int b_len, unsigned char* c_raw, int c_len, struct big_results *res) { 86 | BN_CTX *bctx = BN_CTX_new(); 87 | BIGNUM *a = BN_new(); 88 | BIGNUM *b = BN_new(); 89 | BIGNUM *c = BN_new(); 90 | BIGNUM *res1 = BN_new(); 91 | 92 | BN_bin2bn(a_raw, a_len, a); 93 | BN_bin2bn(b_raw, b_len, b); 94 | BN_bin2bn(c_raw, c_len, c); 95 | 96 | res->a = BN_bn2hex(a); 97 | res->b = BN_bn2hex(b); 98 | res->c = BN_bn2hex(c); 99 | 100 | BN_mod_exp(res1, b, c, a, bctx); 101 | res->exptmod = BN_bn2hex(res1); 102 | 103 | BN_free(a); 104 | BN_free(b); 105 | BN_free(c); 106 | BN_free(res1); 107 | BN_CTX_free(bctx); 108 | } 109 | 110 | int main(int argc, char *argv[]) { 111 | size_t len, l1, l2,l3; 112 | unsigned int divi1, divi2; 113 | unsigned char in[MAXBUF]; 114 | unsigned char *a, *b, *c; 115 | struct big_results openssl_results= {"openssl",0,0,0,0}; 116 | struct big_results gcrypt_results= {"libgcrypt",0,0,0,0}; 117 | 118 | if (argc!=2) { 119 | printf("no file given\n"); 120 | return -1; 121 | } 122 | FILE *f = fopen(argv[1], "rb"); 123 | if (!f) { 124 | printf("can't open file\n"); 125 | return -1; 126 | } 127 | 128 | len = fread(in, sizeof(char), MAXBUF, f); 129 | if (len<5) return -1; 130 | fclose(f); 131 | 132 | divi1=in[0]; 133 | divi2=in[1]; 134 | divi1++;divi2++; 135 | l1 = (len-2)*divi1/256; 136 | l2 = (len-2-l1)*divi2/256; 137 | l3 = (len-2-l1-l2); 138 | assert(l1+l2+l3==len-2); 139 | printf("div1 div2 %i %i\n", divi1, divi2); 140 | printf("len l1 l2 l3 %i %i %i %i\n", (int)len,(int)l1,(int)l2,(int)l3); 141 | a=in+2; 142 | b=in+2+l1; 143 | c=in+2+l1+l2; 144 | 145 | 146 | bntest(a, l1, b, l2, c, l3, &openssl_results); 147 | printres(&openssl_results); 148 | if ((strcmp(openssl_results.a,"0")==0) || (strcmp(openssl_results.c,"0")==0)) return -2; 149 | 150 | gcrytest(a, l1, b, l2, c, l3, &gcrypt_results); 151 | printres(&gcrypt_results); 152 | 153 | assert(strcmp(openssl_results.exptmod, gcrypt_results.exptmod)==0); 154 | 155 | freeres(&openssl_results); 156 | freeres(&gcrypt_results); 157 | 158 | return 0; 159 | } 160 | -------------------------------------------------------------------------------- /openssl-vs-matrixssl-modexp.c: -------------------------------------------------------------------------------- 1 | /* Fuzz-compare the OpenSSL function BN_mod_exp() and the matrixssl function pstm_exptmod(). 2 | * 3 | * To use this you should compile both matrixssl and openssl with american fuzzy lop and then statically link everything together, e.g.: 4 | * afl-clang-fast -o [output] [input] libgcrypto.a libcrypt_s.a libcore_s.a -I[path_to_matrixssl] 5 | * 6 | * Input is a binary file, the first bytes will decide how the rest of the file will be split into three bignums. 7 | * 8 | * by Hanno Böck, license CC0 (public domain) 9 | */ 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #define MAXBUF 1000000 19 | 20 | struct big_results { 21 | char *name; 22 | char *a; 23 | char *b; 24 | char *c; 25 | char *exptmod; 26 | }; 27 | 28 | void printres(struct big_results *res) 29 | { 30 | printf("\n%s:\n", res->name); 31 | printf("a: %s\n", res->a); 32 | printf("b: %s\n", res->b); 33 | printf("c: %s\n", res->c); 34 | printf("b^c mod a: %s\n", res->exptmod); 35 | } 36 | 37 | void freeres(struct big_results *res) 38 | { 39 | free(res->a); 40 | free(res->b); 41 | free(res->c); 42 | free(res->exptmod); 43 | } 44 | 45 | /* test bn functions from openssl/libcrypto */ 46 | void bntest(unsigned char *a_raw, int a_len, unsigned char *b_raw, int b_len, 47 | unsigned char *c_raw, int c_len, struct big_results *res) 48 | { 49 | BN_CTX *bctx = BN_CTX_new(); 50 | BIGNUM *a = BN_new(); 51 | BIGNUM *b = BN_new(); 52 | BIGNUM *c = BN_new(); 53 | BIGNUM *res1 = BN_new(); 54 | 55 | BN_bin2bn(a_raw, a_len, a); 56 | BN_bin2bn(b_raw, b_len, b); 57 | BN_bin2bn(c_raw, c_len, c); 58 | 59 | res->a = BN_bn2hex(a); 60 | res->b = BN_bn2hex(b); 61 | res->c = BN_bn2hex(c); 62 | 63 | BN_mod_exp(res1, b, c, a, bctx); 64 | res->exptmod = BN_bn2hex(res1); 65 | 66 | BN_free(a); 67 | BN_free(b); 68 | BN_free(c); 69 | BN_free(res1); 70 | BN_CTX_free(bctx); 71 | } 72 | 73 | int matrixtest(unsigned char *a_raw, int a_len, unsigned char *b_raw, int b_len, 74 | unsigned char *c_raw, int c_len, struct big_results *res) 75 | { 76 | psPool_t *pool = NULL; 77 | unsigned char *rr = malloc(4096); 78 | char *buf, *buf_ptr; 79 | int i, s; 80 | pstm_int a, b, c, r; 81 | psCryptoOpen("YYYYNNNYYNN"); 82 | 83 | if (pstm_init_for_read_unsigned_bin(pool, &a, a_len) < 0) { 84 | printf("pstm_init_for_read_unsigned_bin a error\n"); 85 | return -1; 86 | } 87 | if (pstm_read_unsigned_bin(&a, a_raw, a_len) != 0) { 88 | printf("pstm_read_unsigned_bin a error\n"); 89 | return -1; 90 | } 91 | if (pstm_init_for_read_unsigned_bin(pool, &b, b_len) < 0) { 92 | printf("pstm_init_for_read_unsigned_bin b error\n"); 93 | return -1; 94 | } 95 | if (pstm_read_unsigned_bin(&b, b_raw, b_len) != 0) { 96 | printf("pstm_read_unsigned_bin b error\n"); 97 | return -1; 98 | } 99 | if (pstm_init_for_read_unsigned_bin(pool, &c, c_len) < 0) { 100 | printf("pstm_init_for_read_unsigned_bin c error\n"); 101 | return -1; 102 | } 103 | if (pstm_read_unsigned_bin(&c, c_raw, c_len) != 0) { 104 | printf("pstm_read_unsigned_bin c error\n"); 105 | return -1; 106 | } 107 | 108 | if (pstm_init(pool, &r) != 0) { 109 | printf("pstm_init r error\n"); 110 | return -1; 111 | } 112 | 113 | if (pstm_exptmod(pool, &b, &c, &a, &r) != 0) { 114 | printf("pstm_exptmod error\n"); 115 | return -1; 116 | } 117 | 118 | if (pstm_to_unsigned_bin(0, &r, rr) < 0) { 119 | printf("pstm_to_unsigned_bin error\n"); 120 | return -1; 121 | } 122 | s = pstm_unsigned_bin_size(&r); 123 | buf = buf_ptr = malloc(s * 2 + 1); 124 | for (i = 0; i < s; i++) { 125 | buf_ptr += sprintf(buf_ptr, "%02X", rr[i]); 126 | } 127 | 128 | res->exptmod = buf; 129 | 130 | /* printf("matrixssl: %s\n", buf);*/ 131 | return 0; 132 | } 133 | 134 | int main(int argc, char *argv[]) 135 | { 136 | size_t len, l1, l2, l3; 137 | unsigned int divi1, divi2; 138 | unsigned char in[MAXBUF]; 139 | unsigned char *a, *b, *c; 140 | struct big_results openssl_results = { "openssl", 0, 0, 0, 0 }; 141 | struct big_results gcrypt_results = { "libgcrypt", 0, 0, 0, 0 }; 142 | struct big_results matrix_results = { "libgcrypt", 0, 0, 0, 0 }; 143 | int i; 144 | 145 | if (argc != 2) { 146 | printf("no file given\n"); 147 | return -1; 148 | } 149 | FILE *f = fopen(argv[1], "rb"); 150 | if (!f) { 151 | printf("can't open file\n"); 152 | return -1; 153 | } 154 | 155 | len = fread(in, sizeof(char), MAXBUF, f); 156 | if (len < 5) 157 | return -1; 158 | fclose(f); 159 | 160 | divi1 = in[0]; 161 | divi2 = in[1]; 162 | divi1++; 163 | divi2++; 164 | l1 = (len - 2) * divi1 / 256; 165 | l2 = (len - 2 - l1) * divi2 / 256; 166 | l3 = (len - 2 - l1 - l2); 167 | assert(l1 + l2 + l3 == len - 2); 168 | #ifdef VERBOSE 169 | printf("div1 div2 %i %i\n", divi1, divi2); 170 | printf("len l1 l2 l3 %i %i %i %i\n", (int)len, (int)l1, (int)l2, 171 | (int)l3); 172 | #endif 173 | a = in + 2; 174 | b = in + 2 + l1; 175 | c = in + 2 + l1 + l2; 176 | 177 | if ((l1 == 0) || (l2 == 0) || (l3 == 0)) 178 | return 2; 179 | 180 | #ifdef VERBOSE 181 | printf("a: \n"); 182 | for (i = 0; i < l1; i++) 183 | printf("%02x:", a[i]); 184 | printf("\nb: \n"); 185 | for (i = 0; i < l2; i++) 186 | printf("%02x:", b[i]); 187 | printf("\nc: \n"); 188 | for (i = 0; i < l3; i++) 189 | printf("%02x:", c[i]); 190 | printf("\n"); 191 | #endif 192 | 193 | if (matrixtest(a, l1, b, l2, c, l3, &matrix_results) ) { 194 | printf("error from matrixssl, probably invalid input\n"); 195 | return 1; 196 | } 197 | 198 | 199 | bntest(a, l1, b, l2, c, l3, &openssl_results); 200 | printres(&openssl_results); 201 | 202 | if (strcmp(openssl_results.b, "0")==0) { 203 | printf("zero base\n"); 204 | return 1; 205 | } 206 | 207 | assert(strcmp(openssl_results.exptmod, matrix_results.exptmod) 208 | == 0); 209 | 210 | freeres(&openssl_results); 211 | freeres(&gcrypt_results); 212 | 213 | return 0; 214 | } 215 | -------------------------------------------------------------------------------- /point-fuzz.c: -------------------------------------------------------------------------------- 1 | /* point-fuzz 2 | * 3 | * Fuzzing elliptic curve scalar multiplications in OpenSSL, Nettle and NSS 4 | * 5 | * To use this preferrably compile a static version of OpenSSL and either Nettle or libmpi/libecl from NSS 6 | * with american fuzzy lop and link them together with this code. 7 | * The defines below decide which curve and which implementation you test. 8 | * (OpenSSL is always enabled, because we need the compressed point setting function.) 9 | * 10 | * ECC implementation notes: 11 | * NSS only implements NISTP256, NISTP384, NISTP521, no NISTP224 12 | * 13 | * Author: Hanno Böck 14 | * License: CC0 / public domain 15 | */ 16 | 17 | #define NETTLE 18 | //#define NSS 19 | 20 | #define NISTP256 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | #ifdef NSS 34 | #define MP_IOFUNC 1 35 | #include "mpi.h" 36 | #include "ecl.h" 37 | #endif 38 | 39 | #define MAXLEN 500 40 | 41 | #ifdef NISTP256 42 | #define CURVEID_OPENSSL NID_X9_62_prime256v1 43 | #define CURVEID_NETTLE nettle_secp_256r1 44 | #define CURVEID_NSS ECCurve_NIST_P256 45 | #define XLEN 32 46 | #endif 47 | 48 | #ifdef NISTP521 49 | #define CURVEID_OPENSSL NID_secp521r1 50 | #define CURVEID_NETTLE nettle_secp_521r1 51 | #define CURVEID_NSS ECCurve_NIST_P521 52 | #define XLEN 65 53 | #endif 54 | 55 | #ifdef NISTP384 56 | #define CURVEID_OPENSSL NID_secp384r1 57 | #define CURVEID_NETTLE nettle_secp_384r1 58 | #define CURVEID_NSS ECCurve_NIST_P384 59 | #define XLEN 48 60 | #endif 61 | 62 | #ifdef NISTP224 63 | #define CURVEID_OPENSSL NID_secp224r1 64 | #define CURVEID_NETTLE nettle_secp_224r1 65 | #define CURVEID_NSS ECCurve_NIST_P224 66 | #define XLEN 28 67 | #endif 68 | 69 | /* Removes leading "+" sign and all leading "0" (except 1 if the result is "0"). */ 70 | char *unify_result(char *in) 71 | { 72 | size_t i = 0; 73 | 74 | if (in[i] == '+') 75 | i++; 76 | 77 | while ((in[i] == '0') && (in[i + 1] != 0)) 78 | i++; 79 | 80 | return &in[i]; 81 | } 82 | 83 | int main(int argc, char *argv[]) 84 | { 85 | size_t len; 86 | unsigned char in[MAXLEN]; 87 | int ret; 88 | 89 | EC_GROUP *curve = EC_GROUP_new_by_curve_name(CURVEID_OPENSSL); 90 | EC_POINT *p1 = EC_POINT_new(curve); 91 | BN_CTX *ctx = BN_CTX_new(); 92 | BIGNUM *x = BN_new(); 93 | BIGNUM *y = BN_new(); 94 | BIGNUM *scal = BN_new(); 95 | BIGNUM *x_ = BN_new(); 96 | BIGNUM *y_ = BN_new(); 97 | char *opensslx, *openssly; 98 | char *hx, *hy, *hs; 99 | 100 | #ifdef NETTLE 101 | mpz_t nx, ny, nscal; 102 | struct ecc_point gp1; 103 | struct ecc_scalar gs1; 104 | char *nettlex, *nettley; 105 | #endif 106 | 107 | #ifdef NSS 108 | /* using prefix m (like mozilla), because n is already taken by nettle) */ 109 | ECGroup *mcurve = ECGroup_fromName(CURVEID_NSS); 110 | mp_int mx, my, ms; 111 | size_t bufsize; 112 | char *nssx, *nssy; 113 | #endif 114 | 115 | if (argc != 2) { 116 | printf("no file given\n"); 117 | return -1; 118 | } 119 | FILE *f = fopen(argv[1], "rb"); 120 | if (!f) { 121 | printf("can't open file\n"); 122 | return -1; 123 | } 124 | 125 | len = fread(in, sizeof(char), MAXLEN, f); 126 | if (len <= (XLEN + 2)) 127 | return -1; 128 | fclose(f); 129 | 130 | BN_bin2bn(&in[1], XLEN, x); 131 | BN_bin2bn(&in[XLEN], len - XLEN - 1, scal); 132 | ret = 133 | EC_POINT_set_compressed_coordinates_GFp(curve, p1, x, in[0] & 1, 134 | ctx); 135 | if (ret != 1) { 136 | printf("error creating point\n"); 137 | return -2; 138 | } 139 | 140 | ret = EC_POINT_is_on_curve(curve, p1, ctx); 141 | if (ret != 1) { 142 | printf("point not on curve\n"); 143 | return -3; 144 | } 145 | 146 | EC_POINT_get_affine_coordinates_GFp(curve, p1, x, y, ctx); 147 | 148 | EC_POINT_mul(curve, p1, 0, p1, scal, ctx); 149 | 150 | EC_POINT_get_affine_coordinates_GFp(curve, p1, x_, y_, ctx); 151 | 152 | opensslx = BN_bn2hex(x_); 153 | openssly = BN_bn2hex(y_); 154 | 155 | hx = BN_bn2hex(x); 156 | hy = BN_bn2hex(y); 157 | hs = BN_bn2hex(scal); 158 | 159 | BN_free(x); 160 | BN_free(y); 161 | BN_free(x_); 162 | BN_free(y_); 163 | BN_free(scal); 164 | EC_POINT_free(p1); 165 | EC_GROUP_free(curve); 166 | BN_CTX_free(ctx); 167 | 168 | printf("Input (x, y, scalar):\n%s\n%s\n%s\n\n", hx, hy, hs); 169 | printf("OpenSSL:\n%s\n%s\n\n", opensslx, openssly); 170 | 171 | #ifdef NETTLE 172 | mpz_init_set_str(nx, hx, 16); 173 | mpz_init_set_str(ny, hy, 16); 174 | mpz_init_set_str(nscal, hs, 16); 175 | 176 | ecc_point_init(&gp1, &CURVEID_NETTLE); 177 | assert(ecc_point_set(&gp1, nx, ny) != 0); 178 | 179 | ecc_scalar_init(&gs1, &CURVEID_NETTLE); 180 | ret = ecc_scalar_set(&gs1, nscal); 181 | if (ret == 0) { 182 | printf("scalar out of range\n"); 183 | return -1; 184 | } 185 | /* scalar out of range */ 186 | ecc_point_mul(&gp1, &gs1, &gp1); 187 | 188 | ecc_point_get(&gp1, nx, ny); 189 | 190 | gmp_asprintf(&nettlex, "%ZX", nx); 191 | gmp_asprintf(&nettley, "%ZX", ny); 192 | 193 | printf("Nettle:\n%s\n%s\n", nettlex, nettley); 194 | assert(strcmp(nettlex, unify_result(opensslx)) == 0); 195 | assert(strcmp(nettley, unify_result(openssly)) == 0); 196 | 197 | mpz_clears(nx, ny, nscal, NULL); 198 | ecc_point_clear(&gp1); 199 | ecc_scalar_clear(&gs1); 200 | free(nettlex); 201 | free(nettley); 202 | #endif 203 | 204 | #ifdef NSS 205 | mp_init(&mx); 206 | mp_init(&my); 207 | mp_init(&ms); 208 | mp_read_radix(&mx, hx, 16); 209 | mp_read_radix(&my, hy, 16); 210 | mp_read_radix(&ms, hs, 16); 211 | 212 | ret = ECPoint_validate(mcurve, &mx, &my); 213 | if (ret == MP_NO) { 214 | printf("nss: point invalid\n"); 215 | return -3; 216 | } 217 | 218 | ECPoint_mul(mcurve, &ms, &mx, &my, &mx, &my); 219 | 220 | f = open_memstream(&nssx, &bufsize); 221 | mp_print(&mx, f); 222 | fclose(f); 223 | f = open_memstream(&nssy, &bufsize); 224 | mp_print(&my, f); 225 | fclose(f); 226 | 227 | mp_clear(&mx); 228 | mp_clear(&my); 229 | mp_clear(&ms); 230 | ECGroup_free(mcurve); 231 | 232 | printf("nss:\n%s\n%s\n", nssx, nssy); 233 | 234 | assert(strcmp(unify_result(nssx), unify_result(opensslx)) == 0); 235 | assert(strcmp(unify_result(nssy), unify_result(openssly)) == 0); 236 | 237 | free(nssx); 238 | free(nssy); 239 | #endif 240 | 241 | free(opensslx); 242 | free(openssly); 243 | free(hx); 244 | free(hy); 245 | free(hs); 246 | 247 | return 0; 248 | } 249 | --------------------------------------------------------------------------------