├── .github └── FUNDING.yml ├── .gitignore ├── Makefile ├── NOTICE ├── README ├── dhtbsign.c ├── libmincrypt ├── Makefile ├── dsa_sig.c ├── p256.c ├── p256_ec.c ├── p256_ecdsa.c ├── rsa.c ├── sha.c └── sha256.c └── mincrypt ├── dsa_sig.h ├── hash-internal.h ├── p256.h ├── p256_ecdsa.h ├── rsa.h ├── sha.h └── sha256.h /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: osm0sis # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | custom: https://www.paypal.me/osm0sis # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 13 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.a 3 | *.exe 4 | dhtbsign 5 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | ifeq ($(CC),cc) 2 | CC = gcc 3 | endif 4 | AR = ar rc 5 | ifeq ($(windir),) 6 | EXT = 7 | RM = rm -f 8 | CP = cp 9 | else 10 | EXT = .exe 11 | RM = del 12 | CP = copy /y 13 | endif 14 | 15 | CFLAGS += -ffunction-sections -O3 16 | 17 | INC = -I. 18 | 19 | ifneq (,$(findstring darwin,$(CROSS_COMPILE))) 20 | UNAME_S := Darwin 21 | else 22 | UNAME_S := $(shell uname -s) 23 | endif 24 | ifeq ($(UNAME_S),Darwin) 25 | LDFLAGS += -Wl,-dead_strip 26 | else 27 | LDFLAGS += -Wl,--gc-sections -s 28 | endif 29 | 30 | all:dhtbsign$(EXT) 31 | 32 | static: 33 | $(MAKE) CFLAGS="$(CFLAGS)" LDFLAGS="$(LDFLAGS) -static" 34 | 35 | libmincrypt.a: 36 | $(MAKE) CFLAGS="$(CFLAGS)" -C libmincrypt 37 | 38 | dhtbsign$(EXT):dhtbsign.o libmincrypt.a 39 | $(CROSS_COMPILE)$(CC) -o $@ $^ -L. -lmincrypt $(LDFLAGS) 40 | 41 | %.o:%.c 42 | $(CROSS_COMPILE)$(CC) -o $@ $(CFLAGS) -c $< $(INC) -Werror 43 | 44 | install: 45 | install -m 755 dhtbsign$(EXT) $(PREFIX)/bin 46 | 47 | clean: 48 | $(RM) dhtbsign 49 | $(RM) *.a *.~ *.exe *.o 50 | $(MAKE) -C libmincrypt clean 51 | 52 | -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | Copyright 2008, The Android Open Source Project 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are met: 5 | * Redistributions of source code must retain the above copyright 6 | notice, this list of conditions and the following disclaimer. 7 | * Redistributions in binary form must reproduce the above copyright 8 | notice, this list of conditions and the following disclaimer in the 9 | documentation and/or other materials provided with the distribution. 10 | * Neither the name of Google Inc. nor the names of its contributors may 11 | be used to endorse or promote products derived from this software 12 | without specific prior written permission. 13 | 14 | THIS SOFTWARE IS PROVIDED BY Google Inc. ``AS IS'' AND ANY EXPRESS OR 15 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 16 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 17 | EVENT SHALL Google Inc. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 18 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 20 | OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 21 | WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 22 | OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 23 | ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | Samsung Tab A 7 DHTB header - reverse engineered (thanks @jedld) 2 | SM-T280 (gtexswifi) 3 | 4 | Original information on the DHTB header/signing here: 5 | https://forum.xda-developers.com/galaxy-tab-a/help/resources-samsung-galaxy-tab-7-0-2016-t3431022/post72734231#post72734231 6 | 7 | Also thanks to @ashyx for research/testing, and many thanks to @chiefwigms for the original mkT280bootimg utility: 8 | https://github.com/chiefwigms/degas-mkbootimg/tree/galaxy_tab_a_smt285 9 | 10 | 11 | DHTB magic: \x44\x48\x54\x42\x01\x00\x00\x00 12 | 13 | payload sha256sum: ANDROID! to SEANDROIDENFORCE + 0xFFFFFFFF 14 | 15 | 8 bytes padding 16 | 17 | payload size: 32-bit unsigned integer in LE 18 | 19 | padded to 512 bytes 20 | 21 | -------------------------------------------------------------------------------- /dhtbsign.c: -------------------------------------------------------------------------------- 1 | /* 2 | * dhtbsign.c - Based on mkT280bootimg by chiefwigms @ xda-developers 3 | * https://github.com/chiefwigms/degas-mkbootimg/blob/galaxy_tab_a_smt285/mkT280bootimg.c 4 | */ 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include "mincrypt/sha256.h" 14 | 15 | const char DHTB_MAGIC[] = {0x44, 0x48, 0x54, 0x42, 0x01, 0x00, 0x00, 0x00}; 16 | #define DHTB_HEADER_SZ 512 17 | #define SHA256_OFFSET 8 18 | #define PAYLOAD_SZ_OFFSET 48 19 | #define BOOT_MAGIC "ANDROID!" 20 | #define BOOT_MAGIC_SZ 8 21 | #define SEANDROID_MAGIC "SEANDROIDENFORCE" 22 | #define SEANDROID_MAGIC_SZ 16 23 | const char PAYLOAD_PADDING[] = {0xFF, 0xFF, 0xFF, 0xFF}; 24 | #define TRAILING_PADDING_SZ 12 25 | 26 | int usage() 27 | { 28 | printf("usage: dhtbsign\n"); 29 | printf("\t-i|--input boot.img\n"); 30 | printf("\t-o|--output boot_dhtb.img\n"); 31 | return 0; 32 | } 33 | 34 | int main (int argc, char** argv) 35 | { 36 | char* iname = NULL; 37 | char* oname = NULL; 38 | char tmp[4096]; 39 | int i; 40 | 41 | argc--; 42 | argv++; 43 | while(argc > 0) { 44 | char *arg = argv[0]; 45 | char *val = argv[1]; 46 | argc -= 2; 47 | argv += 2; 48 | if (!strcmp(arg, "--input") || !strcmp(arg, "-i")) 49 | iname = val; 50 | else if (!strcmp(arg, "--output") || !strcmp(arg, "-o")) 51 | oname = val; 52 | else 53 | return usage(); 54 | } 55 | 56 | if ((iname == NULL) || (oname == NULL)) 57 | return usage(); 58 | 59 | FILE *ifile = fopen(iname, "rb"); 60 | if (ifile == NULL) { 61 | printf("Error opening input file %s!\n", iname); 62 | return usage(); 63 | } 64 | 65 | //Check for DHTB magic 66 | fseek(ifile, 0, SEEK_SET); 67 | if(fread(tmp, sizeof(DHTB_MAGIC), 1, ifile)){}; 68 | if (memcmp(tmp, DHTB_MAGIC, sizeof(DHTB_MAGIC)) == 0) { 69 | printf("DHTB header magic already present!\n"); 70 | fclose(ifile); 71 | return 1; 72 | } 73 | 74 | //Check for ANDROID! magic 75 | fseek(ifile, 0, SEEK_SET); 76 | if(fread(tmp, BOOT_MAGIC_SZ, 1, ifile)){}; 77 | if (memcmp(tmp, BOOT_MAGIC, BOOT_MAGIC_SZ) != 0) { 78 | printf("Android boot magic not found!\n"); 79 | fclose(ifile); 80 | return 1; 81 | } 82 | 83 | //Read boot.img filesize 84 | fseek(ifile, 0, SEEK_END); 85 | long isize = ftell(ifile); 86 | 87 | FILE *ofile = fopen(oname, "wb"); 88 | if (ofile == NULL) { 89 | printf("Error opening output file %s!\n", oname); 90 | fclose(ifile); 91 | return usage(); 92 | } 93 | 94 | //Check if SEANDROIDENFORCE footer and/or 0xFFFFFFFF padding are needed 95 | printf("Input filesize: %ld\n", isize); 96 | int seeklimit = 65536; 97 | int need_seandroid = 1; 98 | int need_plpadding = 1; 99 | for (i = isize - seeklimit; i <= isize; i++) { 100 | fseek(ifile, i, SEEK_SET); 101 | if(fread(tmp, SEANDROID_MAGIC_SZ, 1, ifile)){}; 102 | if (memcmp(tmp, SEANDROID_MAGIC, SEANDROID_MAGIC_SZ) == 0) { 103 | printf("SEAndroid footer at: %d\n", i); 104 | need_seandroid = 0; 105 | i = i + SEANDROID_MAGIC_SZ; 106 | fseek(ifile, i, SEEK_SET); 107 | if(fread(tmp, sizeof(PAYLOAD_PADDING), 1, ifile)){}; 108 | if (memcmp(tmp, PAYLOAD_PADDING, sizeof(PAYLOAD_PADDING)) == 0) { 109 | printf("Payload padding at: %d\n", i); 110 | need_plpadding = 0; 111 | i = i + sizeof(PAYLOAD_PADDING); 112 | } 113 | isize = i; 114 | break; 115 | } 116 | } 117 | printf("Input read size: %ld\n", isize); 118 | 119 | //Allocate header + boot.img size 120 | unsigned char *bootimg = malloc(DHTB_HEADER_SZ + isize); 121 | if (bootimg == NULL) 122 | printf("Error allocating %ld bytes for output file!", (DHTB_HEADER_SZ + isize)); 123 | fseek(ifile, 0, SEEK_SET); 124 | if(fread((DHTB_HEADER_SZ + bootimg), isize, 1, ifile)){}; 125 | fclose(ifile); 126 | 127 | //Append SEANDROIDENFORCE footer and/or 0xFFFFFFFF padding if needed 128 | if (need_seandroid == 1) { 129 | printf("Adding SEANDROIDENFORCE footer...\n"); 130 | memcpy(bootimg + (DHTB_HEADER_SZ + isize), SEANDROID_MAGIC, SEANDROID_MAGIC_SZ); 131 | isize = isize + SEANDROID_MAGIC_SZ; 132 | } 133 | if (need_plpadding == 1) { 134 | printf("Adding payload padding...\n"); 135 | memcpy(bootimg + (DHTB_HEADER_SZ + isize), PAYLOAD_PADDING, sizeof(PAYLOAD_PADDING)); 136 | isize = isize + sizeof(PAYLOAD_PADDING); 137 | } 138 | 139 | //Zero DHTB header 140 | memset(bootimg, 0, DHTB_HEADER_SZ); 141 | 142 | //Calculate payload size 143 | printf("Payload size: %ld\n", isize); 144 | uint32_t psize = isize; 145 | 146 | //Compute SHA256 of payload 147 | SHA256_CTX ctx256; 148 | SHA256_init(&ctx256); 149 | SHA256_update(&ctx256, (DHTB_HEADER_SZ + bootimg), psize); 150 | const uint8_t* sha256 = SHA256_final(&ctx256); 151 | 152 | //Copy MAGIC 153 | memcpy(bootimg, DHTB_MAGIC, sizeof(DHTB_MAGIC)); 154 | 155 | //Copy SHA256 156 | for (i = 0; i < SHA256_DIGEST_SIZE; i++) 157 | bootimg[SHA256_OFFSET+i] = sha256[i]; 158 | 159 | //Copy payload size as LE 160 | bootimg[PAYLOAD_SZ_OFFSET+0] = (psize >> 0) & 0xFF; 161 | bootimg[PAYLOAD_SZ_OFFSET+1] = (psize >> 8) & 0xFF; 162 | bootimg[PAYLOAD_SZ_OFFSET+2] = (psize >> 16) & 0xFF; 163 | bootimg[PAYLOAD_SZ_OFFSET+3] = (psize >> 24) & 0xFF; 164 | 165 | //Write output file with additional padding, close/free 166 | printf("Writing DHTB header + payload...\n"); 167 | fwrite(bootimg, (DHTB_HEADER_SZ + isize + TRAILING_PADDING_SZ), 1, ofile); 168 | fclose(ofile); 169 | free(bootimg); 170 | } 171 | -------------------------------------------------------------------------------- /libmincrypt/Makefile: -------------------------------------------------------------------------------- 1 | ifeq ($(CC),cc) 2 | CC = gcc 3 | endif 4 | AR = ar rc 5 | ifeq ($(windir),) 6 | EXT = 7 | RM = rm -f 8 | CP = cp 9 | else 10 | EXT = .exe 11 | RM = del 12 | CP = copy /y 13 | endif 14 | 15 | CFLAGS += -ffunction-sections -O3 16 | 17 | INC = -I.. 18 | 19 | EXT = .a 20 | LIB = libmincrypt$(EXT) 21 | LIB_OBJS = dsa_sig.o p256.o p256_ec.o p256_ecdsa.o rsa.o sha.o sha256.o 22 | 23 | all:$(LIB) 24 | 25 | $(LIB):$(LIB_OBJS) 26 | $(CROSS_COMPILE)$(AR) $@ $^ 27 | $(CP) $@ .. 28 | 29 | %.o:%.c 30 | $(CROSS_COMPILE)$(CC) -o $@ $(CFLAGS) -c $< $(INC) -Werror 31 | 32 | clean: 33 | $(RM) $(LIB_OBJS) $(LIB) 34 | 35 | -------------------------------------------------------------------------------- /libmincrypt/dsa_sig.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2013 The Android Open Source Project 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright 7 | * notice, this list of conditions and the following disclaimer. 8 | * * Redistributions in binary form must reproduce the above copyright 9 | * notice, this list of conditions and the following disclaimer in the 10 | * documentation and/or other materials provided with the distribution. 11 | * * Neither the name of Google Inc. nor the names of its contributors may 12 | * be used to endorse or promote products derived from this software 13 | * without specific prior written permission. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY Google Inc. ``AS IS'' AND ANY EXPRESS OR 16 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 17 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 18 | * EVENT SHALL Google Inc. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 19 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 20 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 21 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 22 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 23 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 24 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | 27 | #include 28 | 29 | #include "mincrypt/dsa_sig.h" 30 | #include "mincrypt/p256.h" 31 | 32 | /** 33 | * Trims off the leading zero bytes and copy it to a buffer aligning it to the end. 34 | */ 35 | static inline int trim_to_p256_bytes(unsigned char dst[P256_NBYTES], unsigned char *src, 36 | int src_len) { 37 | int dst_offset; 38 | while (*src == '\0' && src_len > 0) { 39 | src++; 40 | src_len--; 41 | } 42 | if (src_len > P256_NBYTES || src_len < 1) { 43 | return 0; 44 | } 45 | dst_offset = P256_NBYTES - src_len; 46 | memset(dst, 0, dst_offset); 47 | memcpy(dst + dst_offset, src, src_len); 48 | return 1; 49 | } 50 | 51 | /** 52 | * Unpacks the ASN.1 DSA signature sequence. 53 | */ 54 | int dsa_sig_unpack(unsigned char* sig, int sig_len, p256_int* r_int, p256_int* s_int) { 55 | /* 56 | * Structure is: 57 | * 0x30 0xNN SEQUENCE + s_length 58 | * 0x02 0xNN INTEGER + r_length 59 | * 0xAA 0xBB .. r_length bytes of "r" (offset 4) 60 | * 0x02 0xNN INTEGER + s_length 61 | * 0xMM 0xNN .. s_length bytes of "s" (offset 6 + r_len) 62 | */ 63 | int seq_len; 64 | unsigned char r_bytes[P256_NBYTES]; 65 | unsigned char s_bytes[P256_NBYTES]; 66 | int r_len; 67 | int s_len; 68 | 69 | memset(r_bytes, 0, sizeof(r_bytes)); 70 | memset(s_bytes, 0, sizeof(s_bytes)); 71 | 72 | /* 73 | * Must have at least: 74 | * 2 bytes sequence header and length 75 | * 2 bytes R integer header and length 76 | * 1 byte of R 77 | * 2 bytes S integer header and length 78 | * 1 byte of S 79 | * 80 | * 8 bytes total 81 | */ 82 | if (sig_len < 8 || sig[0] != 0x30 || sig[2] != 0x02) { 83 | return 0; 84 | } 85 | 86 | seq_len = sig[1]; 87 | if ((seq_len <= 0) || (seq_len + 2 != sig_len)) { 88 | return 0; 89 | } 90 | 91 | r_len = sig[3]; 92 | /* 93 | * Must have at least: 94 | * 2 bytes for R header and length 95 | * 2 bytes S integer header and length 96 | * 1 byte of S 97 | */ 98 | if ((r_len < 1) || (r_len > seq_len - 5) || (sig[4 + r_len] != 0x02)) { 99 | return 0; 100 | } 101 | s_len = sig[5 + r_len]; 102 | 103 | /** 104 | * Must have: 105 | * 2 bytes for R header and length 106 | * r_len bytes for R 107 | * 2 bytes S integer header and length 108 | */ 109 | if ((s_len < 1) || (s_len != seq_len - 4 - r_len)) { 110 | return 0; 111 | } 112 | 113 | /* 114 | * ASN.1 encoded integers are zero-padded for positive integers. Make sure we have 115 | * a correctly-sized buffer and that the resulting integer isn't too large. 116 | */ 117 | if (!trim_to_p256_bytes(r_bytes, &sig[4], r_len) 118 | || !trim_to_p256_bytes(s_bytes, &sig[6 + r_len], s_len)) { 119 | return 0; 120 | } 121 | 122 | p256_from_bin(r_bytes, r_int); 123 | p256_from_bin(s_bytes, s_int); 124 | 125 | return 1; 126 | } 127 | -------------------------------------------------------------------------------- /libmincrypt/p256.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2013 The Android Open Source Project 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright 7 | * notice, this list of conditions and the following disclaimer. 8 | * * Redistributions in binary form must reproduce the above copyright 9 | * notice, this list of conditions and the following disclaimer in the 10 | * documentation and/or other materials provided with the distribution. 11 | * * Neither the name of Google Inc. nor the names of its contributors may 12 | * be used to endorse or promote products derived from this software 13 | * without specific prior written permission. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY Google Inc. ``AS IS'' AND ANY EXPRESS OR 16 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 17 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 18 | * EVENT SHALL Google Inc. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 19 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 20 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 21 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 22 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 23 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 24 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | 27 | // This is an implementation of the P256 elliptic curve group. It's written to 28 | // be portable 32-bit, although it's still constant-time. 29 | // 30 | // WARNING: Implementing these functions in a constant-time manner is far from 31 | // obvious. Be careful when touching this code. 32 | // 33 | // See http://www.imperialviolet.org/2010/12/04/ecc.html ([1]) for background. 34 | 35 | #include 36 | #include 37 | #include 38 | #include 39 | 40 | #include "mincrypt/p256.h" 41 | 42 | const p256_int SECP256r1_n = // curve order 43 | {{0xfc632551, 0xf3b9cac2, 0xa7179e84, 0xbce6faad, -1, -1, 0, -1}}; 44 | 45 | const p256_int SECP256r1_p = // curve field size 46 | {{-1, -1, -1, 0, 0, 0, 1, -1 }}; 47 | 48 | const p256_int SECP256r1_b = // curve b 49 | {{0x27d2604b, 0x3bce3c3e, 0xcc53b0f6, 0x651d06b0, 50 | 0x769886bc, 0xb3ebbd55, 0xaa3a93e7, 0x5ac635d8}}; 51 | 52 | void p256_init(p256_int* a) { 53 | memset(a, 0, sizeof(*a)); 54 | } 55 | 56 | void p256_clear(p256_int* a) { p256_init(a); } 57 | 58 | int p256_get_bit(const p256_int* scalar, int bit) { 59 | return (P256_DIGIT(scalar, bit / P256_BITSPERDIGIT) 60 | >> (bit & (P256_BITSPERDIGIT - 1))) & 1; 61 | } 62 | 63 | int p256_is_zero(const p256_int* a) { 64 | int i, result = 0; 65 | for (i = 0; i < P256_NDIGITS; ++i) result |= P256_DIGIT(a, i); 66 | return !result; 67 | } 68 | 69 | // top, c[] += a[] * b 70 | // Returns new top 71 | static p256_digit mulAdd(const p256_int* a, 72 | p256_digit b, 73 | p256_digit top, 74 | p256_digit* c) { 75 | int i; 76 | p256_ddigit carry = 0; 77 | 78 | for (i = 0; i < P256_NDIGITS; ++i) { 79 | carry += *c; 80 | carry += (p256_ddigit)P256_DIGIT(a, i) * b; 81 | *c++ = (p256_digit)carry; 82 | carry >>= P256_BITSPERDIGIT; 83 | } 84 | return top + (p256_digit)carry; 85 | } 86 | 87 | // top, c[] -= top_a, a[] 88 | static p256_digit subTop(p256_digit top_a, 89 | const p256_digit* a, 90 | p256_digit top_c, 91 | p256_digit* c) { 92 | int i; 93 | p256_sddigit borrow = 0; 94 | 95 | for (i = 0; i < P256_NDIGITS; ++i) { 96 | borrow += *c; 97 | borrow -= *a++; 98 | *c++ = (p256_digit)borrow; 99 | borrow >>= P256_BITSPERDIGIT; 100 | } 101 | borrow += top_c; 102 | borrow -= top_a; 103 | top_c = (p256_digit)borrow; 104 | assert((borrow >> P256_BITSPERDIGIT) == 0); 105 | return top_c; 106 | } 107 | 108 | // top, c[] -= MOD[] & mask (0 or -1) 109 | // returns new top. 110 | static p256_digit subM(const p256_int* MOD, 111 | p256_digit top, 112 | p256_digit* c, 113 | p256_digit mask) { 114 | int i; 115 | p256_sddigit borrow = 0; 116 | for (i = 0; i < P256_NDIGITS; ++i) { 117 | borrow += *c; 118 | borrow -= P256_DIGIT(MOD, i) & mask; 119 | *c++ = (p256_digit)borrow; 120 | borrow >>= P256_BITSPERDIGIT; 121 | } 122 | return top + (p256_digit)borrow; 123 | } 124 | 125 | // top, c[] += MOD[] & mask (0 or -1) 126 | // returns new top. 127 | static p256_digit addM(const p256_int* MOD, 128 | p256_digit top, 129 | p256_digit* c, 130 | p256_digit mask) { 131 | int i; 132 | p256_ddigit carry = 0; 133 | for (i = 0; i < P256_NDIGITS; ++i) { 134 | carry += *c; 135 | carry += P256_DIGIT(MOD, i) & mask; 136 | *c++ = (p256_digit)carry; 137 | carry >>= P256_BITSPERDIGIT; 138 | } 139 | return top + (p256_digit)carry; 140 | } 141 | 142 | // c = a * b mod MOD. c can be a and/or b. 143 | void p256_modmul(const p256_int* MOD, 144 | const p256_int* a, 145 | const p256_digit top_b, 146 | const p256_int* b, 147 | p256_int* c) { 148 | p256_digit tmp[P256_NDIGITS * 2 + 1] = { 0 }; 149 | p256_digit top = 0; 150 | int i; 151 | 152 | // Multiply/add into tmp. 153 | for (i = 0; i < P256_NDIGITS; ++i) { 154 | if (i) tmp[i + P256_NDIGITS - 1] = top; 155 | top = mulAdd(a, P256_DIGIT(b, i), 0, tmp + i); 156 | } 157 | 158 | // Multiply/add top digit 159 | tmp[i + P256_NDIGITS - 1] = top; 160 | top = mulAdd(a, top_b, 0, tmp + i); 161 | 162 | // Reduce tmp, digit by digit. 163 | for (; i >= 0; --i) { 164 | p256_digit reducer[P256_NDIGITS] = { 0 }; 165 | p256_digit top_reducer; 166 | 167 | // top can be any value at this point. 168 | // Guestimate reducer as top * MOD, since msw of MOD is -1. 169 | top_reducer = mulAdd(MOD, top, 0, reducer); 170 | 171 | // Subtract reducer from top | tmp. 172 | top = subTop(top_reducer, reducer, top, tmp + i); 173 | 174 | // top is now either 0 or 1. Make it 0, fixed-timing. 175 | assert(top <= 1); 176 | 177 | top = subM(MOD, top, tmp + i, ~(top - 1)); 178 | 179 | assert(top == 0); 180 | 181 | // We have now reduced the top digit off tmp. Fetch new top digit. 182 | top = tmp[i + P256_NDIGITS - 1]; 183 | } 184 | 185 | // tmp might still be larger than MOD, yet same bit length. 186 | // Make sure it is less, fixed-timing. 187 | addM(MOD, 0, tmp, subM(MOD, 0, tmp, -1)); 188 | 189 | memcpy(c, tmp, P256_NBYTES); 190 | } 191 | int p256_is_odd(const p256_int* a) { return P256_DIGIT(a, 0) & 1; } 192 | int p256_is_even(const p256_int* a) { return !(P256_DIGIT(a, 0) & 1); } 193 | 194 | p256_digit p256_shl(const p256_int* a, int n, p256_int* b) { 195 | int i; 196 | p256_digit top = P256_DIGIT(a, P256_NDIGITS - 1); 197 | 198 | n %= P256_BITSPERDIGIT; 199 | for (i = P256_NDIGITS - 1; i > 0; --i) { 200 | p256_digit accu = (P256_DIGIT(a, i) << n); 201 | accu |= (P256_DIGIT(a, i - 1) >> (P256_BITSPERDIGIT - n)); 202 | P256_DIGIT(b, i) = accu; 203 | } 204 | P256_DIGIT(b, i) = (P256_DIGIT(a, i) << n); 205 | 206 | top = (p256_digit)((((p256_ddigit)top) << n) >> P256_BITSPERDIGIT); 207 | 208 | return top; 209 | } 210 | 211 | void p256_shr(const p256_int* a, int n, p256_int* b) { 212 | int i; 213 | 214 | n %= P256_BITSPERDIGIT; 215 | for (i = 0; i < P256_NDIGITS - 1; ++i) { 216 | p256_digit accu = (P256_DIGIT(a, i) >> n); 217 | accu |= (P256_DIGIT(a, i + 1) << (P256_BITSPERDIGIT - n)); 218 | P256_DIGIT(b, i) = accu; 219 | } 220 | P256_DIGIT(b, i) = (P256_DIGIT(a, i) >> n); 221 | } 222 | 223 | static void p256_shr1(const p256_int* a, int highbit, p256_int* b) { 224 | int i; 225 | 226 | for (i = 0; i < P256_NDIGITS - 1; ++i) { 227 | p256_digit accu = (P256_DIGIT(a, i) >> 1); 228 | accu |= (P256_DIGIT(a, i + 1) << (P256_BITSPERDIGIT - 1)); 229 | P256_DIGIT(b, i) = accu; 230 | } 231 | P256_DIGIT(b, i) = (P256_DIGIT(a, i) >> 1) | 232 | (highbit << (P256_BITSPERDIGIT - 1)); 233 | } 234 | 235 | // Return -1, 0, 1 for a < b, a == b or a > b respectively. 236 | int p256_cmp(const p256_int* a, const p256_int* b) { 237 | int i; 238 | p256_sddigit borrow = 0; 239 | p256_digit notzero = 0; 240 | 241 | for (i = 0; i < P256_NDIGITS; ++i) { 242 | borrow += (p256_sddigit)P256_DIGIT(a, i) - P256_DIGIT(b, i); 243 | // Track whether any result digit is ever not zero. 244 | // Relies on !!(non-zero) evaluating to 1, e.g., !!(-1) evaluating to 1. 245 | notzero |= !!((p256_digit)borrow); 246 | borrow >>= P256_BITSPERDIGIT; 247 | } 248 | return (int)borrow | notzero; 249 | } 250 | 251 | // c = a - b. Returns borrow: 0 or -1. 252 | int p256_sub(const p256_int* a, const p256_int* b, p256_int* c) { 253 | int i; 254 | p256_sddigit borrow = 0; 255 | 256 | for (i = 0; i < P256_NDIGITS; ++i) { 257 | borrow += (p256_sddigit)P256_DIGIT(a, i) - P256_DIGIT(b, i); 258 | if (c) P256_DIGIT(c, i) = (p256_digit)borrow; 259 | borrow >>= P256_BITSPERDIGIT; 260 | } 261 | return (int)borrow; 262 | } 263 | 264 | // c = a + b. Returns carry: 0 or 1. 265 | int p256_add(const p256_int* a, const p256_int* b, p256_int* c) { 266 | int i; 267 | p256_ddigit carry = 0; 268 | 269 | for (i = 0; i < P256_NDIGITS; ++i) { 270 | carry += (p256_ddigit)P256_DIGIT(a, i) + P256_DIGIT(b, i); 271 | if (c) P256_DIGIT(c, i) = (p256_digit)carry; 272 | carry >>= P256_BITSPERDIGIT; 273 | } 274 | return (int)carry; 275 | } 276 | 277 | // b = a + d. Returns carry, 0 or 1. 278 | int p256_add_d(const p256_int* a, p256_digit d, p256_int* b) { 279 | int i; 280 | p256_ddigit carry = d; 281 | 282 | for (i = 0; i < P256_NDIGITS; ++i) { 283 | carry += (p256_ddigit)P256_DIGIT(a, i); 284 | if (b) P256_DIGIT(b, i) = (p256_digit)carry; 285 | carry >>= P256_BITSPERDIGIT; 286 | } 287 | return (int)carry; 288 | } 289 | 290 | // b = 1/a mod MOD, binary euclid. 291 | void p256_modinv_vartime(const p256_int* MOD, 292 | const p256_int* a, 293 | p256_int* b) { 294 | p256_int R = P256_ZERO; 295 | p256_int S = P256_ONE; 296 | p256_int U = *MOD; 297 | p256_int V = *a; 298 | 299 | for (;;) { 300 | if (p256_is_even(&U)) { 301 | p256_shr1(&U, 0, &U); 302 | if (p256_is_even(&R)) { 303 | p256_shr1(&R, 0, &R); 304 | } else { 305 | // R = (R+MOD)/2 306 | p256_shr1(&R, p256_add(&R, MOD, &R), &R); 307 | } 308 | } else if (p256_is_even(&V)) { 309 | p256_shr1(&V, 0, &V); 310 | if (p256_is_even(&S)) { 311 | p256_shr1(&S, 0, &S); 312 | } else { 313 | // S = (S+MOD)/2 314 | p256_shr1(&S, p256_add(&S, MOD, &S) , &S); 315 | } 316 | } else { // U,V both odd. 317 | if (!p256_sub(&V, &U, NULL)) { 318 | p256_sub(&V, &U, &V); 319 | if (p256_sub(&S, &R, &S)) p256_add(&S, MOD, &S); 320 | if (p256_is_zero(&V)) break; // done. 321 | } else { 322 | p256_sub(&U, &V, &U); 323 | if (p256_sub(&R, &S, &R)) p256_add(&R, MOD, &R); 324 | } 325 | } 326 | } 327 | 328 | p256_mod(MOD, &R, b); 329 | } 330 | 331 | void p256_mod(const p256_int* MOD, 332 | const p256_int* in, 333 | p256_int* out) { 334 | if (out != in) *out = *in; 335 | addM(MOD, 0, P256_DIGITS(out), subM(MOD, 0, P256_DIGITS(out), -1)); 336 | } 337 | 338 | // Verify y^2 == x^3 - 3x + b mod p 339 | // and 0 < x < p and 0 < y < p 340 | int p256_is_valid_point(const p256_int* x, const p256_int* y) { 341 | p256_int y2, x3; 342 | 343 | if (p256_cmp(&SECP256r1_p, x) <= 0 || 344 | p256_cmp(&SECP256r1_p, y) <= 0 || 345 | p256_is_zero(x) || 346 | p256_is_zero(y)) return 0; 347 | 348 | p256_modmul(&SECP256r1_p, y, 0, y, &y2); // y^2 349 | 350 | p256_modmul(&SECP256r1_p, x, 0, x, &x3); // x^2 351 | p256_modmul(&SECP256r1_p, x, 0, &x3, &x3); // x^3 352 | if (p256_sub(&x3, x, &x3)) p256_add(&x3, &SECP256r1_p, &x3); // x^3 - x 353 | if (p256_sub(&x3, x, &x3)) p256_add(&x3, &SECP256r1_p, &x3); // x^3 - 2x 354 | if (p256_sub(&x3, x, &x3)) p256_add(&x3, &SECP256r1_p, &x3); // x^3 - 3x 355 | if (p256_add(&x3, &SECP256r1_b, &x3)) // x^3 - 3x + b 356 | p256_sub(&x3, &SECP256r1_p, &x3); 357 | 358 | return p256_cmp(&y2, &x3) == 0; 359 | } 360 | 361 | void p256_from_bin(const uint8_t src[P256_NBYTES], p256_int* dst) { 362 | int i; 363 | const uint8_t* p = &src[0]; 364 | 365 | for (i = P256_NDIGITS - 1; i >= 0; --i) { 366 | P256_DIGIT(dst, i) = 367 | (p[0] << 24) | 368 | (p[1] << 16) | 369 | (p[2] << 8) | 370 | p[3]; 371 | p += 4; 372 | } 373 | } 374 | -------------------------------------------------------------------------------- /libmincrypt/p256_ec.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2013 The Android Open Source Project 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright 7 | * notice, this list of conditions and the following disclaimer. 8 | * * Redistributions in binary form must reproduce the above copyright 9 | * notice, this list of conditions and the following disclaimer in the 10 | * documentation and/or other materials provided with the distribution. 11 | * * Neither the name of Google Inc. nor the names of its contributors may 12 | * be used to endorse or promote products derived from this software 13 | * without specific prior written permission. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY Google Inc. ``AS IS'' AND ANY EXPRESS OR 16 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 17 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 18 | * EVENT SHALL Google Inc. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 19 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 20 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 21 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 22 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 23 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 24 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | 27 | // This is an implementation of the P256 elliptic curve group. It's written to 28 | // be portable 32-bit, although it's still constant-time. 29 | // 30 | // WARNING: Implementing these functions in a constant-time manner is far from 31 | // obvious. Be careful when touching this code. 32 | // 33 | // See http://www.imperialviolet.org/2010/12/04/ecc.html ([1]) for background. 34 | 35 | #include 36 | #include 37 | 38 | #include 39 | #include 40 | 41 | #include "mincrypt/p256.h" 42 | 43 | typedef uint8_t u8; 44 | typedef uint32_t u32; 45 | typedef int32_t s32; 46 | typedef uint64_t u64; 47 | 48 | /* Our field elements are represented as nine 32-bit limbs. 49 | * 50 | * The value of an felem (field element) is: 51 | * x[0] + (x[1] * 2**29) + (x[2] * 2**57) + ... + (x[8] * 2**228) 52 | * 53 | * That is, each limb is alternately 29 or 28-bits wide in little-endian 54 | * order. 55 | * 56 | * This means that an felem hits 2**257, rather than 2**256 as we would like. A 57 | * 28, 29, ... pattern would cause us to hit 2**256, but that causes problems 58 | * when multiplying as terms end up one bit short of a limb which would require 59 | * much bit-shifting to correct. 60 | * 61 | * Finally, the values stored in an felem are in Montgomery form. So the value 62 | * |y| is stored as (y*R) mod p, where p is the P-256 prime and R is 2**257. 63 | */ 64 | typedef u32 limb; 65 | #define NLIMBS 9 66 | typedef limb felem[NLIMBS]; 67 | 68 | static const limb kBottom28Bits = 0xfffffff; 69 | static const limb kBottom29Bits = 0x1fffffff; 70 | 71 | /* kOne is the number 1 as an felem. It's 2**257 mod p split up into 29 and 72 | * 28-bit words. */ 73 | static const felem kOne = { 74 | 2, 0, 0, 0xffff800, 75 | 0x1fffffff, 0xfffffff, 0x1fbfffff, 0x1ffffff, 76 | 0 77 | }; 78 | static const felem kZero = {0}; 79 | static const felem kP = { 80 | 0x1fffffff, 0xfffffff, 0x1fffffff, 0x3ff, 81 | 0, 0, 0x200000, 0xf000000, 82 | 0xfffffff 83 | }; 84 | static const felem k2P = { 85 | 0x1ffffffe, 0xfffffff, 0x1fffffff, 0x7ff, 86 | 0, 0, 0x400000, 0xe000000, 87 | 0x1fffffff 88 | }; 89 | /* kPrecomputed contains precomputed values to aid the calculation of scalar 90 | * multiples of the base point, G. It's actually two, equal length, tables 91 | * concatenated. 92 | * 93 | * The first table contains (x,y) felem pairs for 16 multiples of the base 94 | * point, G. 95 | * 96 | * Index | Index (binary) | Value 97 | * 0 | 0000 | 0G (all zeros, omitted) 98 | * 1 | 0001 | G 99 | * 2 | 0010 | 2**64G 100 | * 3 | 0011 | 2**64G + G 101 | * 4 | 0100 | 2**128G 102 | * 5 | 0101 | 2**128G + G 103 | * 6 | 0110 | 2**128G + 2**64G 104 | * 7 | 0111 | 2**128G + 2**64G + G 105 | * 8 | 1000 | 2**192G 106 | * 9 | 1001 | 2**192G + G 107 | * 10 | 1010 | 2**192G + 2**64G 108 | * 11 | 1011 | 2**192G + 2**64G + G 109 | * 12 | 1100 | 2**192G + 2**128G 110 | * 13 | 1101 | 2**192G + 2**128G + G 111 | * 14 | 1110 | 2**192G + 2**128G + 2**64G 112 | * 15 | 1111 | 2**192G + 2**128G + 2**64G + G 113 | * 114 | * The second table follows the same style, but the terms are 2**32G, 115 | * 2**96G, 2**160G, 2**224G. 116 | * 117 | * This is ~2KB of data. */ 118 | static const limb kPrecomputed[NLIMBS * 2 * 15 * 2] = { 119 | 0x11522878, 0xe730d41, 0xdb60179, 0x4afe2ff, 0x12883add, 0xcaddd88, 0x119e7edc, 0xd4a6eab, 0x3120bee, 120 | 0x1d2aac15, 0xf25357c, 0x19e45cdd, 0x5c721d0, 0x1992c5a5, 0xa237487, 0x154ba21, 0x14b10bb, 0xae3fe3, 121 | 0xd41a576, 0x922fc51, 0x234994f, 0x60b60d3, 0x164586ae, 0xce95f18, 0x1fe49073, 0x3fa36cc, 0x5ebcd2c, 122 | 0xb402f2f, 0x15c70bf, 0x1561925c, 0x5a26704, 0xda91e90, 0xcdc1c7f, 0x1ea12446, 0xe1ade1e, 0xec91f22, 123 | 0x26f7778, 0x566847e, 0xa0bec9e, 0x234f453, 0x1a31f21a, 0xd85e75c, 0x56c7109, 0xa267a00, 0xb57c050, 124 | 0x98fb57, 0xaa837cc, 0x60c0792, 0xcfa5e19, 0x61bab9e, 0x589e39b, 0xa324c5, 0x7d6dee7, 0x2976e4b, 125 | 0x1fc4124a, 0xa8c244b, 0x1ce86762, 0xcd61c7e, 0x1831c8e0, 0x75774e1, 0x1d96a5a9, 0x843a649, 0xc3ab0fa, 126 | 0x6e2e7d5, 0x7673a2a, 0x178b65e8, 0x4003e9b, 0x1a1f11c2, 0x7816ea, 0xf643e11, 0x58c43df, 0xf423fc2, 127 | 0x19633ffa, 0x891f2b2, 0x123c231c, 0x46add8c, 0x54700dd, 0x59e2b17, 0x172db40f, 0x83e277d, 0xb0dd609, 128 | 0xfd1da12, 0x35c6e52, 0x19ede20c, 0xd19e0c0, 0x97d0f40, 0xb015b19, 0x449e3f5, 0xe10c9e, 0x33ab581, 129 | 0x56a67ab, 0x577734d, 0x1dddc062, 0xc57b10d, 0x149b39d, 0x26a9e7b, 0xc35df9f, 0x48764cd, 0x76dbcca, 130 | 0xca4b366, 0xe9303ab, 0x1a7480e7, 0x57e9e81, 0x1e13eb50, 0xf466cf3, 0x6f16b20, 0x4ba3173, 0xc168c33, 131 | 0x15cb5439, 0x6a38e11, 0x73658bd, 0xb29564f, 0x3f6dc5b, 0x53b97e, 0x1322c4c0, 0x65dd7ff, 0x3a1e4f6, 132 | 0x14e614aa, 0x9246317, 0x1bc83aca, 0xad97eed, 0xd38ce4a, 0xf82b006, 0x341f077, 0xa6add89, 0x4894acd, 133 | 0x9f162d5, 0xf8410ef, 0x1b266a56, 0xd7f223, 0x3e0cb92, 0xe39b672, 0x6a2901a, 0x69a8556, 0x7e7c0, 134 | 0x9b7d8d3, 0x309a80, 0x1ad05f7f, 0xc2fb5dd, 0xcbfd41d, 0x9ceb638, 0x1051825c, 0xda0cf5b, 0x812e881, 135 | 0x6f35669, 0x6a56f2c, 0x1df8d184, 0x345820, 0x1477d477, 0x1645db1, 0xbe80c51, 0xc22be3e, 0xe35e65a, 136 | 0x1aeb7aa0, 0xc375315, 0xf67bc99, 0x7fdd7b9, 0x191fc1be, 0x61235d, 0x2c184e9, 0x1c5a839, 0x47a1e26, 137 | 0xb7cb456, 0x93e225d, 0x14f3c6ed, 0xccc1ac9, 0x17fe37f3, 0x4988989, 0x1a90c502, 0x2f32042, 0xa17769b, 138 | 0xafd8c7c, 0x8191c6e, 0x1dcdb237, 0x16200c0, 0x107b32a1, 0x66c08db, 0x10d06a02, 0x3fc93, 0x5620023, 139 | 0x16722b27, 0x68b5c59, 0x270fcfc, 0xfad0ecc, 0xe5de1c2, 0xeab466b, 0x2fc513c, 0x407f75c, 0xbaab133, 140 | 0x9705fe9, 0xb88b8e7, 0x734c993, 0x1e1ff8f, 0x19156970, 0xabd0f00, 0x10469ea7, 0x3293ac0, 0xcdc98aa, 141 | 0x1d843fd, 0xe14bfe8, 0x15be825f, 0x8b5212, 0xeb3fb67, 0x81cbd29, 0xbc62f16, 0x2b6fcc7, 0xf5a4e29, 142 | 0x13560b66, 0xc0b6ac2, 0x51ae690, 0xd41e271, 0xf3e9bd4, 0x1d70aab, 0x1029f72, 0x73e1c35, 0xee70fbc, 143 | 0xad81baf, 0x9ecc49a, 0x86c741e, 0xfe6be30, 0x176752e7, 0x23d416, 0x1f83de85, 0x27de188, 0x66f70b8, 144 | 0x181cd51f, 0x96b6e4c, 0x188f2335, 0xa5df759, 0x17a77eb6, 0xfeb0e73, 0x154ae914, 0x2f3ec51, 0x3826b59, 145 | 0xb91f17d, 0x1c72949, 0x1362bf0a, 0xe23fddf, 0xa5614b0, 0xf7d8f, 0x79061, 0x823d9d2, 0x8213f39, 146 | 0x1128ae0b, 0xd095d05, 0xb85c0c2, 0x1ecb2ef, 0x24ddc84, 0xe35e901, 0x18411a4a, 0xf5ddc3d, 0x3786689, 147 | 0x52260e8, 0x5ae3564, 0x542b10d, 0x8d93a45, 0x19952aa4, 0x996cc41, 0x1051a729, 0x4be3499, 0x52b23aa, 148 | 0x109f307e, 0x6f5b6bb, 0x1f84e1e7, 0x77a0cfa, 0x10c4df3f, 0x25a02ea, 0xb048035, 0xe31de66, 0xc6ecaa3, 149 | 0x28ea335, 0x2886024, 0x1372f020, 0xf55d35, 0x15e4684c, 0xf2a9e17, 0x1a4a7529, 0xcb7beb1, 0xb2a78a1, 150 | 0x1ab21f1f, 0x6361ccf, 0x6c9179d, 0xb135627, 0x1267b974, 0x4408bad, 0x1cbff658, 0xe3d6511, 0xc7d76f, 151 | 0x1cc7a69, 0xe7ee31b, 0x54fab4f, 0x2b914f, 0x1ad27a30, 0xcd3579e, 0xc50124c, 0x50daa90, 0xb13f72, 152 | 0xb06aa75, 0x70f5cc6, 0x1649e5aa, 0x84a5312, 0x329043c, 0x41c4011, 0x13d32411, 0xb04a838, 0xd760d2d, 153 | 0x1713b532, 0xbaa0c03, 0x84022ab, 0x6bcf5c1, 0x2f45379, 0x18ae070, 0x18c9e11e, 0x20bca9a, 0x66f496b, 154 | 0x3eef294, 0x67500d2, 0xd7f613c, 0x2dbbeb, 0xb741038, 0xe04133f, 0x1582968d, 0xbe985f7, 0x1acbc1a, 155 | 0x1a6a939f, 0x33e50f6, 0xd665ed4, 0xb4b7bd6, 0x1e5a3799, 0x6b33847, 0x17fa56ff, 0x65ef930, 0x21dc4a, 156 | 0x2b37659, 0x450fe17, 0xb357b65, 0xdf5efac, 0x15397bef, 0x9d35a7f, 0x112ac15f, 0x624e62e, 0xa90ae2f, 157 | 0x107eecd2, 0x1f69bbe, 0x77d6bce, 0x5741394, 0x13c684fc, 0x950c910, 0x725522b, 0xdc78583, 0x40eeabb, 158 | 0x1fde328a, 0xbd61d96, 0xd28c387, 0x9e77d89, 0x12550c40, 0x759cb7d, 0x367ef34, 0xae2a960, 0x91b8bdc, 159 | 0x93462a9, 0xf469ef, 0xb2e9aef, 0xd2ca771, 0x54e1f42, 0x7aaa49, 0x6316abb, 0x2413c8e, 0x5425bf9, 160 | 0x1bed3e3a, 0xf272274, 0x1f5e7326, 0x6416517, 0xea27072, 0x9cedea7, 0x6e7633, 0x7c91952, 0xd806dce, 161 | 0x8e2a7e1, 0xe421e1a, 0x418c9e1, 0x1dbc890, 0x1b395c36, 0xa1dc175, 0x1dc4ef73, 0x8956f34, 0xe4b5cf2, 162 | 0x1b0d3a18, 0x3194a36, 0x6c2641f, 0xe44124c, 0xa2f4eaa, 0xa8c25ba, 0xf927ed7, 0x627b614, 0x7371cca, 163 | 0xba16694, 0x417bc03, 0x7c0a7e3, 0x9c35c19, 0x1168a205, 0x8b6b00d, 0x10e3edc9, 0x9c19bf2, 0x5882229, 164 | 0x1b2b4162, 0xa5cef1a, 0x1543622b, 0x9bd433e, 0x364e04d, 0x7480792, 0x5c9b5b3, 0xe85ff25, 0x408ef57, 165 | 0x1814cfa4, 0x121b41b, 0xd248a0f, 0x3b05222, 0x39bb16a, 0xc75966d, 0xa038113, 0xa4a1769, 0x11fbc6c, 166 | 0x917e50e, 0xeec3da8, 0x169d6eac, 0x10c1699, 0xa416153, 0xf724912, 0x15cd60b7, 0x4acbad9, 0x5efc5fa, 167 | 0xf150ed7, 0x122b51, 0x1104b40a, 0xcb7f442, 0xfbb28ff, 0x6ac53ca, 0x196142cc, 0x7bf0fa9, 0x957651, 168 | 0x4e0f215, 0xed439f8, 0x3f46bd5, 0x5ace82f, 0x110916b6, 0x6db078, 0xffd7d57, 0xf2ecaac, 0xca86dec, 169 | 0x15d6b2da, 0x965ecc9, 0x1c92b4c2, 0x1f3811, 0x1cb080f5, 0x2d8b804, 0x19d1c12d, 0xf20bd46, 0x1951fa7, 170 | 0xa3656c3, 0x523a425, 0xfcd0692, 0xd44ddc8, 0x131f0f5b, 0xaf80e4a, 0xcd9fc74, 0x99bb618, 0x2db944c, 171 | 0xa673090, 0x1c210e1, 0x178c8d23, 0x1474383, 0x10b8743d, 0x985a55b, 0x2e74779, 0x576138, 0x9587927, 172 | 0x133130fa, 0xbe05516, 0x9f4d619, 0xbb62570, 0x99ec591, 0xd9468fe, 0x1d07782d, 0xfc72e0b, 0x701b298, 173 | 0x1863863b, 0x85954b8, 0x121a0c36, 0x9e7fedf, 0xf64b429, 0x9b9d71e, 0x14e2f5d8, 0xf858d3a, 0x942eea8, 174 | 0xda5b765, 0x6edafff, 0xa9d18cc, 0xc65e4ba, 0x1c747e86, 0xe4ea915, 0x1981d7a1, 0x8395659, 0x52ed4e2, 175 | 0x87d43b7, 0x37ab11b, 0x19d292ce, 0xf8d4692, 0x18c3053f, 0x8863e13, 0x4c146c0, 0x6bdf55a, 0x4e4457d, 176 | 0x16152289, 0xac78ec2, 0x1a59c5a2, 0x2028b97, 0x71c2d01, 0x295851f, 0x404747b, 0x878558d, 0x7d29aa4, 177 | 0x13d8341f, 0x8daefd7, 0x139c972d, 0x6b7ea75, 0xd4a9dde, 0xff163d8, 0x81d55d7, 0xa5bef68, 0xb7b30d8, 178 | 0xbe73d6f, 0xaa88141, 0xd976c81, 0x7e7a9cc, 0x18beb771, 0xd773cbd, 0x13f51951, 0x9d0c177, 0x1c49a78, 179 | }; 180 | 181 | 182 | /* Field element operations: */ 183 | 184 | /* NON_ZERO_TO_ALL_ONES returns: 185 | * 0xffffffff for 0 < x <= 2**31 186 | * 0 for x == 0 or x > 2**31. 187 | * 188 | * x must be a u32 or an equivalent type such as limb. */ 189 | #define NON_ZERO_TO_ALL_ONES(x) ((((u32)(x) - 1) >> 31) - 1) 190 | 191 | /* felem_reduce_carry adds a multiple of p in order to cancel |carry|, 192 | * which is a term at 2**257. 193 | * 194 | * On entry: carry < 2**3, inout[0,2,...] < 2**29, inout[1,3,...] < 2**28. 195 | * On exit: inout[0,2,..] < 2**30, inout[1,3,...] < 2**29. */ 196 | static void felem_reduce_carry(felem inout, limb carry) { 197 | const u32 carry_mask = NON_ZERO_TO_ALL_ONES(carry); 198 | 199 | inout[0] += carry << 1; 200 | inout[3] += 0x10000000 & carry_mask; 201 | /* carry < 2**3 thus (carry << 11) < 2**14 and we added 2**28 in the 202 | * previous line therefore this doesn't underflow. */ 203 | inout[3] -= carry << 11; 204 | inout[4] += (0x20000000 - 1) & carry_mask; 205 | inout[5] += (0x10000000 - 1) & carry_mask; 206 | inout[6] += (0x20000000 - 1) & carry_mask; 207 | inout[6] -= carry << 22; 208 | /* This may underflow if carry is non-zero but, if so, we'll fix it in the 209 | * next line. */ 210 | inout[7] -= 1 & carry_mask; 211 | inout[7] += carry << 25; 212 | } 213 | 214 | /* felem_sum sets out = in+in2. 215 | * 216 | * On entry, in[i]+in2[i] must not overflow a 32-bit word. 217 | * On exit: out[0,2,...] < 2**30, out[1,3,...] < 2**29 */ 218 | static void felem_sum(felem out, const felem in, const felem in2) { 219 | limb carry = 0; 220 | unsigned i; 221 | 222 | for (i = 0;; i++) { 223 | out[i] = in[i] + in2[i]; 224 | out[i] += carry; 225 | carry = out[i] >> 29; 226 | out[i] &= kBottom29Bits; 227 | 228 | i++; 229 | if (i == NLIMBS) 230 | break; 231 | 232 | out[i] = in[i] + in2[i]; 233 | out[i] += carry; 234 | carry = out[i] >> 28; 235 | out[i] &= kBottom28Bits; 236 | } 237 | 238 | felem_reduce_carry(out, carry); 239 | } 240 | 241 | #define two31m3 (((limb)1) << 31) - (((limb)1) << 3) 242 | #define two30m2 (((limb)1) << 30) - (((limb)1) << 2) 243 | #define two30p13m2 (((limb)1) << 30) + (((limb)1) << 13) - (((limb)1) << 2) 244 | #define two31m2 (((limb)1) << 31) - (((limb)1) << 2) 245 | #define two31p24m2 (((limb)1) << 31) + (((limb)1) << 24) - (((limb)1) << 2) 246 | #define two30m27m2 (((limb)1) << 30) - (((limb)1) << 27) - (((limb)1) << 2) 247 | 248 | /* zero31 is 0 mod p. */ 249 | static const felem zero31 = { two31m3, two30m2, two31m2, two30p13m2, two31m2, two30m2, two31p24m2, two30m27m2, two31m2 }; 250 | 251 | /* felem_diff sets out = in-in2. 252 | * 253 | * On entry: in[0,2,...] < 2**30, in[1,3,...] < 2**29 and 254 | * in2[0,2,...] < 2**30, in2[1,3,...] < 2**29. 255 | * On exit: out[0,2,...] < 2**30, out[1,3,...] < 2**29. */ 256 | static void felem_diff(felem out, const felem in, const felem in2) { 257 | limb carry = 0; 258 | unsigned i; 259 | 260 | for (i = 0;; i++) { 261 | out[i] = in[i] - in2[i]; 262 | out[i] += zero31[i]; 263 | out[i] += carry; 264 | carry = out[i] >> 29; 265 | out[i] &= kBottom29Bits; 266 | 267 | i++; 268 | if (i == NLIMBS) 269 | break; 270 | 271 | out[i] = in[i] - in2[i]; 272 | out[i] += zero31[i]; 273 | out[i] += carry; 274 | carry = out[i] >> 28; 275 | out[i] &= kBottom28Bits; 276 | } 277 | 278 | felem_reduce_carry(out, carry); 279 | } 280 | 281 | /* felem_reduce_degree sets out = tmp/R mod p where tmp contains 64-bit words 282 | * with the same 29,28,... bit positions as an felem. 283 | * 284 | * The values in felems are in Montgomery form: x*R mod p where R = 2**257. 285 | * Since we just multiplied two Montgomery values together, the result is 286 | * x*y*R*R mod p. We wish to divide by R in order for the result also to be 287 | * in Montgomery form. 288 | * 289 | * On entry: tmp[i] < 2**64 290 | * On exit: out[0,2,...] < 2**30, out[1,3,...] < 2**29 */ 291 | static void felem_reduce_degree(felem out, u64 tmp[17]) { 292 | /* The following table may be helpful when reading this code: 293 | * 294 | * Limb number: 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10... 295 | * Width (bits): 29| 28| 29| 28| 29| 28| 29| 28| 29| 28| 29 296 | * Start bit: 0 | 29| 57| 86|114|143|171|200|228|257|285 297 | * (odd phase): 0 | 28| 57| 85|114|142|171|199|228|256|285 */ 298 | limb tmp2[18], carry, x, xMask; 299 | unsigned i; 300 | 301 | /* tmp contains 64-bit words with the same 29,28,29-bit positions as an 302 | * felem. So the top of an element of tmp might overlap with another 303 | * element two positions down. The following loop eliminates this 304 | * overlap. */ 305 | tmp2[0] = (limb)(tmp[0] & kBottom29Bits); 306 | 307 | /* In the following we use "(limb) tmp[x]" and "(limb) (tmp[x]>>32)" to try 308 | * and hint to the compiler that it can do a single-word shift by selecting 309 | * the right register rather than doing a double-word shift and truncating 310 | * afterwards. */ 311 | tmp2[1] = ((limb) tmp[0]) >> 29; 312 | tmp2[1] |= (((limb)(tmp[0] >> 32)) << 3) & kBottom28Bits; 313 | tmp2[1] += ((limb) tmp[1]) & kBottom28Bits; 314 | carry = tmp2[1] >> 28; 315 | tmp2[1] &= kBottom28Bits; 316 | 317 | for (i = 2; i < 17; i++) { 318 | tmp2[i] = ((limb)(tmp[i - 2] >> 32)) >> 25; 319 | tmp2[i] += ((limb)(tmp[i - 1])) >> 28; 320 | tmp2[i] += (((limb)(tmp[i - 1] >> 32)) << 4) & kBottom29Bits; 321 | tmp2[i] += ((limb) tmp[i]) & kBottom29Bits; 322 | tmp2[i] += carry; 323 | carry = tmp2[i] >> 29; 324 | tmp2[i] &= kBottom29Bits; 325 | 326 | i++; 327 | if (i == 17) 328 | break; 329 | tmp2[i] = ((limb)(tmp[i - 2] >> 32)) >> 25; 330 | tmp2[i] += ((limb)(tmp[i - 1])) >> 29; 331 | tmp2[i] += (((limb)(tmp[i - 1] >> 32)) << 3) & kBottom28Bits; 332 | tmp2[i] += ((limb) tmp[i]) & kBottom28Bits; 333 | tmp2[i] += carry; 334 | carry = tmp2[i] >> 28; 335 | tmp2[i] &= kBottom28Bits; 336 | } 337 | 338 | tmp2[17] = ((limb)(tmp[15] >> 32)) >> 25; 339 | tmp2[17] += ((limb)(tmp[16])) >> 29; 340 | tmp2[17] += (((limb)(tmp[16] >> 32)) << 3); 341 | tmp2[17] += carry; 342 | 343 | /* Montgomery elimination of terms. 344 | * 345 | * Since R is 2**257, we can divide by R with a bitwise shift if we can 346 | * ensure that the right-most 257 bits are all zero. We can make that true by 347 | * adding multiplies of p without affecting the value. 348 | * 349 | * So we eliminate limbs from right to left. Since the bottom 29 bits of p 350 | * are all ones, then by adding tmp2[0]*p to tmp2 we'll make tmp2[0] == 0. 351 | * We can do that for 8 further limbs and then right shift to eliminate the 352 | * extra factor of R. */ 353 | for (i = 0;; i += 2) { 354 | tmp2[i + 1] += tmp2[i] >> 29; 355 | x = tmp2[i] & kBottom29Bits; 356 | xMask = NON_ZERO_TO_ALL_ONES(x); 357 | tmp2[i] = 0; 358 | 359 | /* The bounds calculations for this loop are tricky. Each iteration of 360 | * the loop eliminates two words by adding values to words to their 361 | * right. 362 | * 363 | * The following table contains the amounts added to each word (as an 364 | * offset from the value of i at the top of the loop). The amounts are 365 | * accounted for from the first and second half of the loop separately 366 | * and are written as, for example, 28 to mean a value <2**28. 367 | * 368 | * Word: 3 4 5 6 7 8 9 10 369 | * Added in top half: 28 11 29 21 29 28 370 | * 28 29 371 | * 29 372 | * Added in bottom half: 29 10 28 21 28 28 373 | * 29 374 | * 375 | * The value that is currently offset 7 will be offset 5 for the next 376 | * iteration and then offset 3 for the iteration after that. Therefore 377 | * the total value added will be the values added at 7, 5 and 3. 378 | * 379 | * The following table accumulates these values. The sums at the bottom 380 | * are written as, for example, 29+28, to mean a value < 2**29+2**28. 381 | * 382 | * Word: 3 4 5 6 7 8 9 10 11 12 13 383 | * 28 11 10 29 21 29 28 28 28 28 28 384 | * 29 28 11 28 29 28 29 28 29 28 385 | * 29 28 21 21 29 21 29 21 386 | * 10 29 28 21 28 21 28 387 | * 28 29 28 29 28 29 28 388 | * 11 10 29 10 29 10 389 | * 29 28 11 28 11 390 | * 29 29 391 | * -------------------------------------------- 392 | * 30+ 31+ 30+ 31+ 30+ 393 | * 28+ 29+ 28+ 29+ 21+ 394 | * 21+ 28+ 21+ 28+ 10 395 | * 10 21+ 10 21+ 396 | * 11 11 397 | * 398 | * So the greatest amount is added to tmp2[10] and tmp2[12]. If 399 | * tmp2[10/12] has an initial value of <2**29, then the maximum value 400 | * will be < 2**31 + 2**30 + 2**28 + 2**21 + 2**11, which is < 2**32, 401 | * as required. */ 402 | tmp2[i + 3] += (x << 10) & kBottom28Bits; 403 | tmp2[i + 4] += (x >> 18); 404 | 405 | tmp2[i + 6] += (x << 21) & kBottom29Bits; 406 | tmp2[i + 7] += x >> 8; 407 | 408 | /* At position 200, which is the starting bit position for word 7, we 409 | * have a factor of 0xf000000 = 2**28 - 2**24. */ 410 | tmp2[i + 7] += 0x10000000 & xMask; 411 | /* Word 7 is 28 bits wide, so the 2**28 term exactly hits word 8. */ 412 | tmp2[i + 8] += (x - 1) & xMask; 413 | tmp2[i + 7] -= (x << 24) & kBottom28Bits; 414 | tmp2[i + 8] -= x >> 4; 415 | 416 | tmp2[i + 8] += 0x20000000 & xMask; 417 | tmp2[i + 8] -= x; 418 | tmp2[i + 8] += (x << 28) & kBottom29Bits; 419 | tmp2[i + 9] += ((x >> 1) - 1) & xMask; 420 | 421 | if (i+1 == NLIMBS) 422 | break; 423 | tmp2[i + 2] += tmp2[i + 1] >> 28; 424 | x = tmp2[i + 1] & kBottom28Bits; 425 | xMask = NON_ZERO_TO_ALL_ONES(x); 426 | tmp2[i + 1] = 0; 427 | 428 | tmp2[i + 4] += (x << 11) & kBottom29Bits; 429 | tmp2[i + 5] += (x >> 18); 430 | 431 | tmp2[i + 7] += (x << 21) & kBottom28Bits; 432 | tmp2[i + 8] += x >> 7; 433 | 434 | /* At position 199, which is the starting bit of the 8th word when 435 | * dealing with a context starting on an odd word, we have a factor of 436 | * 0x1e000000 = 2**29 - 2**25. Since we have not updated i, the 8th 437 | * word from i+1 is i+8. */ 438 | tmp2[i + 8] += 0x20000000 & xMask; 439 | tmp2[i + 9] += (x - 1) & xMask; 440 | tmp2[i + 8] -= (x << 25) & kBottom29Bits; 441 | tmp2[i + 9] -= x >> 4; 442 | 443 | tmp2[i + 9] += 0x10000000 & xMask; 444 | tmp2[i + 9] -= x; 445 | tmp2[i + 10] += (x - 1) & xMask; 446 | } 447 | 448 | /* We merge the right shift with a carry chain. The words above 2**257 have 449 | * widths of 28,29,... which we need to correct when copying them down. */ 450 | carry = 0; 451 | for (i = 0; i < 8; i++) { 452 | /* The maximum value of tmp2[i + 9] occurs on the first iteration and 453 | * is < 2**30+2**29+2**28. Adding 2**29 (from tmp2[i + 10]) is 454 | * therefore safe. */ 455 | out[i] = tmp2[i + 9]; 456 | out[i] += carry; 457 | out[i] += (tmp2[i + 10] << 28) & kBottom29Bits; 458 | carry = out[i] >> 29; 459 | out[i] &= kBottom29Bits; 460 | 461 | i++; 462 | out[i] = tmp2[i + 9] >> 1; 463 | out[i] += carry; 464 | carry = out[i] >> 28; 465 | out[i] &= kBottom28Bits; 466 | } 467 | 468 | out[8] = tmp2[17]; 469 | out[8] += carry; 470 | carry = out[8] >> 29; 471 | out[8] &= kBottom29Bits; 472 | 473 | felem_reduce_carry(out, carry); 474 | } 475 | 476 | /* felem_square sets out=in*in. 477 | * 478 | * On entry: in[0,2,...] < 2**30, in[1,3,...] < 2**29. 479 | * On exit: out[0,2,...] < 2**30, out[1,3,...] < 2**29. */ 480 | static void felem_square(felem out, const felem in) { 481 | u64 tmp[17]; 482 | 483 | tmp[0] = ((u64) in[0]) * in[0]; 484 | tmp[1] = ((u64) in[0]) * (in[1] << 1); 485 | tmp[2] = ((u64) in[0]) * (in[2] << 1) + 486 | ((u64) in[1]) * (in[1] << 1); 487 | tmp[3] = ((u64) in[0]) * (in[3] << 1) + 488 | ((u64) in[1]) * (in[2] << 1); 489 | tmp[4] = ((u64) in[0]) * (in[4] << 1) + 490 | ((u64) in[1]) * (in[3] << 2) + ((u64) in[2]) * in[2]; 491 | tmp[5] = ((u64) in[0]) * (in[5] << 1) + ((u64) in[1]) * 492 | (in[4] << 1) + ((u64) in[2]) * (in[3] << 1); 493 | tmp[6] = ((u64) in[0]) * (in[6] << 1) + ((u64) in[1]) * 494 | (in[5] << 2) + ((u64) in[2]) * (in[4] << 1) + 495 | ((u64) in[3]) * (in[3] << 1); 496 | tmp[7] = ((u64) in[0]) * (in[7] << 1) + ((u64) in[1]) * 497 | (in[6] << 1) + ((u64) in[2]) * (in[5] << 1) + 498 | ((u64) in[3]) * (in[4] << 1); 499 | /* tmp[8] has the greatest value of 2**61 + 2**60 + 2**61 + 2**60 + 2**60, 500 | * which is < 2**64 as required. */ 501 | tmp[8] = ((u64) in[0]) * (in[8] << 1) + ((u64) in[1]) * 502 | (in[7] << 2) + ((u64) in[2]) * (in[6] << 1) + 503 | ((u64) in[3]) * (in[5] << 2) + ((u64) in[4]) * in[4]; 504 | tmp[9] = ((u64) in[1]) * (in[8] << 1) + ((u64) in[2]) * 505 | (in[7] << 1) + ((u64) in[3]) * (in[6] << 1) + 506 | ((u64) in[4]) * (in[5] << 1); 507 | tmp[10] = ((u64) in[2]) * (in[8] << 1) + ((u64) in[3]) * 508 | (in[7] << 2) + ((u64) in[4]) * (in[6] << 1) + 509 | ((u64) in[5]) * (in[5] << 1); 510 | tmp[11] = ((u64) in[3]) * (in[8] << 1) + ((u64) in[4]) * 511 | (in[7] << 1) + ((u64) in[5]) * (in[6] << 1); 512 | tmp[12] = ((u64) in[4]) * (in[8] << 1) + 513 | ((u64) in[5]) * (in[7] << 2) + ((u64) in[6]) * in[6]; 514 | tmp[13] = ((u64) in[5]) * (in[8] << 1) + 515 | ((u64) in[6]) * (in[7] << 1); 516 | tmp[14] = ((u64) in[6]) * (in[8] << 1) + 517 | ((u64) in[7]) * (in[7] << 1); 518 | tmp[15] = ((u64) in[7]) * (in[8] << 1); 519 | tmp[16] = ((u64) in[8]) * in[8]; 520 | 521 | felem_reduce_degree(out, tmp); 522 | } 523 | 524 | /* felem_mul sets out=in*in2. 525 | * 526 | * On entry: in[0,2,...] < 2**30, in[1,3,...] < 2**29 and 527 | * in2[0,2,...] < 2**30, in2[1,3,...] < 2**29. 528 | * On exit: out[0,2,...] < 2**30, out[1,3,...] < 2**29. */ 529 | static void felem_mul(felem out, const felem in, const felem in2) { 530 | u64 tmp[17]; 531 | 532 | tmp[0] = ((u64) in[0]) * in2[0]; 533 | tmp[1] = ((u64) in[0]) * (in2[1] << 0) + 534 | ((u64) in[1]) * (in2[0] << 0); 535 | tmp[2] = ((u64) in[0]) * (in2[2] << 0) + ((u64) in[1]) * 536 | (in2[1] << 1) + ((u64) in[2]) * (in2[0] << 0); 537 | tmp[3] = ((u64) in[0]) * (in2[3] << 0) + ((u64) in[1]) * 538 | (in2[2] << 0) + ((u64) in[2]) * (in2[1] << 0) + 539 | ((u64) in[3]) * (in2[0] << 0); 540 | tmp[4] = ((u64) in[0]) * (in2[4] << 0) + ((u64) in[1]) * 541 | (in2[3] << 1) + ((u64) in[2]) * (in2[2] << 0) + 542 | ((u64) in[3]) * (in2[1] << 1) + 543 | ((u64) in[4]) * (in2[0] << 0); 544 | tmp[5] = ((u64) in[0]) * (in2[5] << 0) + ((u64) in[1]) * 545 | (in2[4] << 0) + ((u64) in[2]) * (in2[3] << 0) + 546 | ((u64) in[3]) * (in2[2] << 0) + ((u64) in[4]) * 547 | (in2[1] << 0) + ((u64) in[5]) * (in2[0] << 0); 548 | tmp[6] = ((u64) in[0]) * (in2[6] << 0) + ((u64) in[1]) * 549 | (in2[5] << 1) + ((u64) in[2]) * (in2[4] << 0) + 550 | ((u64) in[3]) * (in2[3] << 1) + ((u64) in[4]) * 551 | (in2[2] << 0) + ((u64) in[5]) * (in2[1] << 1) + 552 | ((u64) in[6]) * (in2[0] << 0); 553 | tmp[7] = ((u64) in[0]) * (in2[7] << 0) + ((u64) in[1]) * 554 | (in2[6] << 0) + ((u64) in[2]) * (in2[5] << 0) + 555 | ((u64) in[3]) * (in2[4] << 0) + ((u64) in[4]) * 556 | (in2[3] << 0) + ((u64) in[5]) * (in2[2] << 0) + 557 | ((u64) in[6]) * (in2[1] << 0) + 558 | ((u64) in[7]) * (in2[0] << 0); 559 | /* tmp[8] has the greatest value but doesn't overflow. See logic in 560 | * felem_square. */ 561 | tmp[8] = ((u64) in[0]) * (in2[8] << 0) + ((u64) in[1]) * 562 | (in2[7] << 1) + ((u64) in[2]) * (in2[6] << 0) + 563 | ((u64) in[3]) * (in2[5] << 1) + ((u64) in[4]) * 564 | (in2[4] << 0) + ((u64) in[5]) * (in2[3] << 1) + 565 | ((u64) in[6]) * (in2[2] << 0) + ((u64) in[7]) * 566 | (in2[1] << 1) + ((u64) in[8]) * (in2[0] << 0); 567 | tmp[9] = ((u64) in[1]) * (in2[8] << 0) + ((u64) in[2]) * 568 | (in2[7] << 0) + ((u64) in[3]) * (in2[6] << 0) + 569 | ((u64) in[4]) * (in2[5] << 0) + ((u64) in[5]) * 570 | (in2[4] << 0) + ((u64) in[6]) * (in2[3] << 0) + 571 | ((u64) in[7]) * (in2[2] << 0) + 572 | ((u64) in[8]) * (in2[1] << 0); 573 | tmp[10] = ((u64) in[2]) * (in2[8] << 0) + ((u64) in[3]) * 574 | (in2[7] << 1) + ((u64) in[4]) * (in2[6] << 0) + 575 | ((u64) in[5]) * (in2[5] << 1) + ((u64) in[6]) * 576 | (in2[4] << 0) + ((u64) in[7]) * (in2[3] << 1) + 577 | ((u64) in[8]) * (in2[2] << 0); 578 | tmp[11] = ((u64) in[3]) * (in2[8] << 0) + ((u64) in[4]) * 579 | (in2[7] << 0) + ((u64) in[5]) * (in2[6] << 0) + 580 | ((u64) in[6]) * (in2[5] << 0) + ((u64) in[7]) * 581 | (in2[4] << 0) + ((u64) in[8]) * (in2[3] << 0); 582 | tmp[12] = ((u64) in[4]) * (in2[8] << 0) + ((u64) in[5]) * 583 | (in2[7] << 1) + ((u64) in[6]) * (in2[6] << 0) + 584 | ((u64) in[7]) * (in2[5] << 1) + 585 | ((u64) in[8]) * (in2[4] << 0); 586 | tmp[13] = ((u64) in[5]) * (in2[8] << 0) + ((u64) in[6]) * 587 | (in2[7] << 0) + ((u64) in[7]) * (in2[6] << 0) + 588 | ((u64) in[8]) * (in2[5] << 0); 589 | tmp[14] = ((u64) in[6]) * (in2[8] << 0) + ((u64) in[7]) * 590 | (in2[7] << 1) + ((u64) in[8]) * (in2[6] << 0); 591 | tmp[15] = ((u64) in[7]) * (in2[8] << 0) + 592 | ((u64) in[8]) * (in2[7] << 0); 593 | tmp[16] = ((u64) in[8]) * (in2[8] << 0); 594 | 595 | felem_reduce_degree(out, tmp); 596 | } 597 | 598 | static void felem_assign(felem out, const felem in) { 599 | memcpy(out, in, sizeof(felem)); 600 | } 601 | 602 | /* felem_inv calculates |out| = |in|^{-1} 603 | * 604 | * Based on Fermat's Little Theorem: 605 | * a^p = a (mod p) 606 | * a^{p-1} = 1 (mod p) 607 | * a^{p-2} = a^{-1} (mod p) 608 | */ 609 | static void felem_inv(felem out, const felem in) { 610 | felem ftmp, ftmp2; 611 | /* each e_I will hold |in|^{2^I - 1} */ 612 | felem e2, e4, e8, e16, e32, e64; 613 | unsigned i; 614 | 615 | felem_square(ftmp, in); /* 2^1 */ 616 | felem_mul(ftmp, in, ftmp); /* 2^2 - 2^0 */ 617 | felem_assign(e2, ftmp); 618 | felem_square(ftmp, ftmp); /* 2^3 - 2^1 */ 619 | felem_square(ftmp, ftmp); /* 2^4 - 2^2 */ 620 | felem_mul(ftmp, ftmp, e2); /* 2^4 - 2^0 */ 621 | felem_assign(e4, ftmp); 622 | felem_square(ftmp, ftmp); /* 2^5 - 2^1 */ 623 | felem_square(ftmp, ftmp); /* 2^6 - 2^2 */ 624 | felem_square(ftmp, ftmp); /* 2^7 - 2^3 */ 625 | felem_square(ftmp, ftmp); /* 2^8 - 2^4 */ 626 | felem_mul(ftmp, ftmp, e4); /* 2^8 - 2^0 */ 627 | felem_assign(e8, ftmp); 628 | for (i = 0; i < 8; i++) { 629 | felem_square(ftmp, ftmp); 630 | } /* 2^16 - 2^8 */ 631 | felem_mul(ftmp, ftmp, e8); /* 2^16 - 2^0 */ 632 | felem_assign(e16, ftmp); 633 | for (i = 0; i < 16; i++) { 634 | felem_square(ftmp, ftmp); 635 | } /* 2^32 - 2^16 */ 636 | felem_mul(ftmp, ftmp, e16); /* 2^32 - 2^0 */ 637 | felem_assign(e32, ftmp); 638 | for (i = 0; i < 32; i++) { 639 | felem_square(ftmp, ftmp); 640 | } /* 2^64 - 2^32 */ 641 | felem_assign(e64, ftmp); 642 | felem_mul(ftmp, ftmp, in); /* 2^64 - 2^32 + 2^0 */ 643 | for (i = 0; i < 192; i++) { 644 | felem_square(ftmp, ftmp); 645 | } /* 2^256 - 2^224 + 2^192 */ 646 | 647 | felem_mul(ftmp2, e64, e32); /* 2^64 - 2^0 */ 648 | for (i = 0; i < 16; i++) { 649 | felem_square(ftmp2, ftmp2); 650 | } /* 2^80 - 2^16 */ 651 | felem_mul(ftmp2, ftmp2, e16); /* 2^80 - 2^0 */ 652 | for (i = 0; i < 8; i++) { 653 | felem_square(ftmp2, ftmp2); 654 | } /* 2^88 - 2^8 */ 655 | felem_mul(ftmp2, ftmp2, e8); /* 2^88 - 2^0 */ 656 | for (i = 0; i < 4; i++) { 657 | felem_square(ftmp2, ftmp2); 658 | } /* 2^92 - 2^4 */ 659 | felem_mul(ftmp2, ftmp2, e4); /* 2^92 - 2^0 */ 660 | felem_square(ftmp2, ftmp2); /* 2^93 - 2^1 */ 661 | felem_square(ftmp2, ftmp2); /* 2^94 - 2^2 */ 662 | felem_mul(ftmp2, ftmp2, e2); /* 2^94 - 2^0 */ 663 | felem_square(ftmp2, ftmp2); /* 2^95 - 2^1 */ 664 | felem_square(ftmp2, ftmp2); /* 2^96 - 2^2 */ 665 | felem_mul(ftmp2, ftmp2, in); /* 2^96 - 3 */ 666 | 667 | felem_mul(out, ftmp2, ftmp); /* 2^256 - 2^224 + 2^192 + 2^96 - 3 */ 668 | } 669 | 670 | /* felem_scalar_3 sets out=3*out. 671 | * 672 | * On entry: out[0,2,...] < 2**30, out[1,3,...] < 2**29. 673 | * On exit: out[0,2,...] < 2**30, out[1,3,...] < 2**29. */ 674 | static void felem_scalar_3(felem out) { 675 | limb carry = 0; 676 | unsigned i; 677 | 678 | for (i = 0;; i++) { 679 | out[i] *= 3; 680 | out[i] += carry; 681 | carry = out[i] >> 29; 682 | out[i] &= kBottom29Bits; 683 | 684 | i++; 685 | if (i == NLIMBS) 686 | break; 687 | 688 | out[i] *= 3; 689 | out[i] += carry; 690 | carry = out[i] >> 28; 691 | out[i] &= kBottom28Bits; 692 | } 693 | 694 | felem_reduce_carry(out, carry); 695 | } 696 | 697 | /* felem_scalar_4 sets out=4*out. 698 | * 699 | * On entry: out[0,2,...] < 2**30, out[1,3,...] < 2**29. 700 | * On exit: out[0,2,...] < 2**30, out[1,3,...] < 2**29. */ 701 | static void felem_scalar_4(felem out) { 702 | limb carry = 0, next_carry; 703 | unsigned i; 704 | 705 | for (i = 0;; i++) { 706 | next_carry = out[i] >> 27; 707 | out[i] <<= 2; 708 | out[i] &= kBottom29Bits; 709 | out[i] += carry; 710 | carry = next_carry + (out[i] >> 29); 711 | out[i] &= kBottom29Bits; 712 | 713 | i++; 714 | if (i == NLIMBS) 715 | break; 716 | 717 | next_carry = out[i] >> 26; 718 | out[i] <<= 2; 719 | out[i] &= kBottom28Bits; 720 | out[i] += carry; 721 | carry = next_carry + (out[i] >> 28); 722 | out[i] &= kBottom28Bits; 723 | } 724 | 725 | felem_reduce_carry(out, carry); 726 | } 727 | 728 | /* felem_scalar_8 sets out=8*out. 729 | * 730 | * On entry: out[0,2,...] < 2**30, out[1,3,...] < 2**29. 731 | * On exit: out[0,2,...] < 2**30, out[1,3,...] < 2**29. */ 732 | static void felem_scalar_8(felem out) { 733 | limb carry = 0, next_carry; 734 | unsigned i; 735 | 736 | for (i = 0;; i++) { 737 | next_carry = out[i] >> 26; 738 | out[i] <<= 3; 739 | out[i] &= kBottom29Bits; 740 | out[i] += carry; 741 | carry = next_carry + (out[i] >> 29); 742 | out[i] &= kBottom29Bits; 743 | 744 | i++; 745 | if (i == NLIMBS) 746 | break; 747 | 748 | next_carry = out[i] >> 25; 749 | out[i] <<= 3; 750 | out[i] &= kBottom28Bits; 751 | out[i] += carry; 752 | carry = next_carry + (out[i] >> 28); 753 | out[i] &= kBottom28Bits; 754 | } 755 | 756 | felem_reduce_carry(out, carry); 757 | } 758 | 759 | /* felem_is_zero_vartime returns 1 iff |in| == 0. It takes a variable amount of 760 | * time depending on the value of |in|. */ 761 | static char felem_is_zero_vartime(const felem in) { 762 | limb carry; 763 | int i; 764 | limb tmp[NLIMBS]; 765 | 766 | felem_assign(tmp, in); 767 | 768 | /* First, reduce tmp to a minimal form. */ 769 | do { 770 | carry = 0; 771 | for (i = 0;; i++) { 772 | tmp[i] += carry; 773 | carry = tmp[i] >> 29; 774 | tmp[i] &= kBottom29Bits; 775 | 776 | i++; 777 | if (i == NLIMBS) 778 | break; 779 | 780 | tmp[i] += carry; 781 | carry = tmp[i] >> 28; 782 | tmp[i] &= kBottom28Bits; 783 | } 784 | 785 | felem_reduce_carry(tmp, carry); 786 | } while (carry); 787 | 788 | /* tmp < 2**257, so the only possible zero values are 0, p and 2p. */ 789 | return memcmp(tmp, kZero, sizeof(tmp)) == 0 || 790 | memcmp(tmp, kP, sizeof(tmp)) == 0 || 791 | memcmp(tmp, k2P, sizeof(tmp)) == 0; 792 | } 793 | 794 | 795 | /* Group operations: 796 | * 797 | * Elements of the elliptic curve group are represented in Jacobian 798 | * coordinates: (x, y, z). An affine point (x', y') is x'=x/z**2, y'=y/z**3 in 799 | * Jacobian form. */ 800 | 801 | /* point_double sets {x_out,y_out,z_out} = 2*{x,y,z}. 802 | * 803 | * See http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#doubling-dbl-2009-l */ 804 | static void point_double(felem x_out, felem y_out, felem z_out, const felem x, 805 | const felem y, const felem z) { 806 | felem delta, gamma, alpha, beta, tmp, tmp2; 807 | 808 | felem_square(delta, z); 809 | felem_square(gamma, y); 810 | felem_mul(beta, x, gamma); 811 | 812 | felem_sum(tmp, x, delta); 813 | felem_diff(tmp2, x, delta); 814 | felem_mul(alpha, tmp, tmp2); 815 | felem_scalar_3(alpha); 816 | 817 | felem_sum(tmp, y, z); 818 | felem_square(tmp, tmp); 819 | felem_diff(tmp, tmp, gamma); 820 | felem_diff(z_out, tmp, delta); 821 | 822 | felem_scalar_4(beta); 823 | felem_square(x_out, alpha); 824 | felem_diff(x_out, x_out, beta); 825 | felem_diff(x_out, x_out, beta); 826 | 827 | felem_diff(tmp, beta, x_out); 828 | felem_mul(tmp, alpha, tmp); 829 | felem_square(tmp2, gamma); 830 | felem_scalar_8(tmp2); 831 | felem_diff(y_out, tmp, tmp2); 832 | } 833 | 834 | /* point_add_mixed sets {x_out,y_out,z_out} = {x1,y1,z1} + {x2,y2,1}. 835 | * (i.e. the second point is affine.) 836 | * 837 | * See http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#addition-add-2007-bl 838 | * 839 | * Note that this function does not handle P+P, infinity+P nor P+infinity 840 | * correctly. */ 841 | static void point_add_mixed(felem x_out, felem y_out, felem z_out, 842 | const felem x1, const felem y1, const felem z1, 843 | const felem x2, const felem y2) { 844 | felem z1z1, z1z1z1, s2, u2, h, i, j, r, rr, v, tmp; 845 | 846 | felem_square(z1z1, z1); 847 | felem_sum(tmp, z1, z1); 848 | 849 | felem_mul(u2, x2, z1z1); 850 | felem_mul(z1z1z1, z1, z1z1); 851 | felem_mul(s2, y2, z1z1z1); 852 | felem_diff(h, u2, x1); 853 | felem_sum(i, h, h); 854 | felem_square(i, i); 855 | felem_mul(j, h, i); 856 | felem_diff(r, s2, y1); 857 | felem_sum(r, r, r); 858 | felem_mul(v, x1, i); 859 | 860 | felem_mul(z_out, tmp, h); 861 | felem_square(rr, r); 862 | felem_diff(x_out, rr, j); 863 | felem_diff(x_out, x_out, v); 864 | felem_diff(x_out, x_out, v); 865 | 866 | felem_diff(tmp, v, x_out); 867 | felem_mul(y_out, tmp, r); 868 | felem_mul(tmp, y1, j); 869 | felem_diff(y_out, y_out, tmp); 870 | felem_diff(y_out, y_out, tmp); 871 | } 872 | 873 | /* point_add sets {x_out,y_out,z_out} = {x1,y1,z1} + {x2,y2,z2}. 874 | * 875 | * See http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#addition-add-2007-bl 876 | * 877 | * Note that this function does not handle P+P, infinity+P nor P+infinity 878 | * correctly. */ 879 | static void point_add(felem x_out, felem y_out, felem z_out, const felem x1, 880 | const felem y1, const felem z1, const felem x2, 881 | const felem y2, const felem z2) { 882 | felem z1z1, z1z1z1, z2z2, z2z2z2, s1, s2, u1, u2, h, i, j, r, rr, v, tmp; 883 | 884 | felem_square(z1z1, z1); 885 | felem_square(z2z2, z2); 886 | felem_mul(u1, x1, z2z2); 887 | 888 | felem_sum(tmp, z1, z2); 889 | felem_square(tmp, tmp); 890 | felem_diff(tmp, tmp, z1z1); 891 | felem_diff(tmp, tmp, z2z2); 892 | 893 | felem_mul(z2z2z2, z2, z2z2); 894 | felem_mul(s1, y1, z2z2z2); 895 | 896 | felem_mul(u2, x2, z1z1); 897 | felem_mul(z1z1z1, z1, z1z1); 898 | felem_mul(s2, y2, z1z1z1); 899 | felem_diff(h, u2, u1); 900 | felem_sum(i, h, h); 901 | felem_square(i, i); 902 | felem_mul(j, h, i); 903 | felem_diff(r, s2, s1); 904 | felem_sum(r, r, r); 905 | felem_mul(v, u1, i); 906 | 907 | felem_mul(z_out, tmp, h); 908 | felem_square(rr, r); 909 | felem_diff(x_out, rr, j); 910 | felem_diff(x_out, x_out, v); 911 | felem_diff(x_out, x_out, v); 912 | 913 | felem_diff(tmp, v, x_out); 914 | felem_mul(y_out, tmp, r); 915 | felem_mul(tmp, s1, j); 916 | felem_diff(y_out, y_out, tmp); 917 | felem_diff(y_out, y_out, tmp); 918 | } 919 | 920 | /* point_add_or_double_vartime sets {x_out,y_out,z_out} = {x1,y1,z1} + 921 | * {x2,y2,z2}. 922 | * 923 | * See http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#addition-add-2007-bl 924 | * 925 | * This function handles the case where {x1,y1,z1}={x2,y2,z2}. */ 926 | static void point_add_or_double_vartime( 927 | felem x_out, felem y_out, felem z_out, const felem x1, const felem y1, 928 | const felem z1, const felem x2, const felem y2, const felem z2) { 929 | felem z1z1, z1z1z1, z2z2, z2z2z2, s1, s2, u1, u2, h, i, j, r, rr, v, tmp; 930 | char x_equal, y_equal; 931 | 932 | felem_square(z1z1, z1); 933 | felem_square(z2z2, z2); 934 | felem_mul(u1, x1, z2z2); 935 | 936 | felem_sum(tmp, z1, z2); 937 | felem_square(tmp, tmp); 938 | felem_diff(tmp, tmp, z1z1); 939 | felem_diff(tmp, tmp, z2z2); 940 | 941 | felem_mul(z2z2z2, z2, z2z2); 942 | felem_mul(s1, y1, z2z2z2); 943 | 944 | felem_mul(u2, x2, z1z1); 945 | felem_mul(z1z1z1, z1, z1z1); 946 | felem_mul(s2, y2, z1z1z1); 947 | felem_diff(h, u2, u1); 948 | x_equal = felem_is_zero_vartime(h); 949 | felem_sum(i, h, h); 950 | felem_square(i, i); 951 | felem_mul(j, h, i); 952 | felem_diff(r, s2, s1); 953 | y_equal = felem_is_zero_vartime(r); 954 | if (x_equal && y_equal) { 955 | point_double(x_out, y_out, z_out, x1, y1, z1); 956 | return; 957 | } 958 | felem_sum(r, r, r); 959 | felem_mul(v, u1, i); 960 | 961 | felem_mul(z_out, tmp, h); 962 | felem_square(rr, r); 963 | felem_diff(x_out, rr, j); 964 | felem_diff(x_out, x_out, v); 965 | felem_diff(x_out, x_out, v); 966 | 967 | felem_diff(tmp, v, x_out); 968 | felem_mul(y_out, tmp, r); 969 | felem_mul(tmp, s1, j); 970 | felem_diff(y_out, y_out, tmp); 971 | felem_diff(y_out, y_out, tmp); 972 | } 973 | 974 | /* copy_conditional sets out=in if mask = 0xffffffff in constant time. 975 | * 976 | * On entry: mask is either 0 or 0xffffffff. */ 977 | static void copy_conditional(felem out, const felem in, limb mask) { 978 | int i; 979 | 980 | for (i = 0; i < NLIMBS; i++) { 981 | const limb tmp = mask & (in[i] ^ out[i]); 982 | out[i] ^= tmp; 983 | } 984 | } 985 | 986 | /* select_affine_point sets {out_x,out_y} to the index'th entry of table. 987 | * On entry: index < 16, table[0] must be zero. */ 988 | static void select_affine_point(felem out_x, felem out_y, const limb* table, 989 | limb index) { 990 | limb i, j; 991 | 992 | memset(out_x, 0, sizeof(felem)); 993 | memset(out_y, 0, sizeof(felem)); 994 | 995 | for (i = 1; i < 16; i++) { 996 | limb mask = i ^ index; 997 | mask |= mask >> 2; 998 | mask |= mask >> 1; 999 | mask &= 1; 1000 | mask--; 1001 | for (j = 0; j < NLIMBS; j++, table++) { 1002 | out_x[j] |= *table & mask; 1003 | } 1004 | for (j = 0; j < NLIMBS; j++, table++) { 1005 | out_y[j] |= *table & mask; 1006 | } 1007 | } 1008 | } 1009 | 1010 | /* select_jacobian_point sets {out_x,out_y,out_z} to the index'th entry of 1011 | * table. On entry: index < 16, table[0] must be zero. */ 1012 | static void select_jacobian_point(felem out_x, felem out_y, felem out_z, 1013 | const limb* table, limb index) { 1014 | limb i, j; 1015 | 1016 | memset(out_x, 0, sizeof(felem)); 1017 | memset(out_y, 0, sizeof(felem)); 1018 | memset(out_z, 0, sizeof(felem)); 1019 | 1020 | /* The implicit value at index 0 is all zero. We don't need to perform that 1021 | * iteration of the loop because we already set out_* to zero. */ 1022 | table += 3 * NLIMBS; 1023 | 1024 | // Hit all entries to obscure cache profiling. 1025 | for (i = 1; i < 16; i++) { 1026 | limb mask = i ^ index; 1027 | mask |= mask >> 2; 1028 | mask |= mask >> 1; 1029 | mask &= 1; 1030 | mask--; 1031 | for (j = 0; j < NLIMBS; j++, table++) { 1032 | out_x[j] |= *table & mask; 1033 | } 1034 | for (j = 0; j < NLIMBS; j++, table++) { 1035 | out_y[j] |= *table & mask; 1036 | } 1037 | for (j = 0; j < NLIMBS; j++, table++) { 1038 | out_z[j] |= *table & mask; 1039 | } 1040 | } 1041 | } 1042 | 1043 | /* scalar_base_mult sets {nx,ny,nz} = scalar*G where scalar is a little-endian 1044 | * number. Note that the value of scalar must be less than the order of the 1045 | * group. */ 1046 | static void scalar_base_mult(felem nx, felem ny, felem nz, 1047 | const p256_int* scalar) { 1048 | int i, j; 1049 | limb n_is_infinity_mask = -1, p_is_noninfinite_mask, mask; 1050 | u32 table_offset; 1051 | 1052 | felem px, py; 1053 | felem tx, ty, tz; 1054 | 1055 | memset(nx, 0, sizeof(felem)); 1056 | memset(ny, 0, sizeof(felem)); 1057 | memset(nz, 0, sizeof(felem)); 1058 | 1059 | /* The loop adds bits at positions 0, 64, 128 and 192, followed by 1060 | * positions 32,96,160 and 224 and does this 32 times. */ 1061 | for (i = 0; i < 32; i++) { 1062 | if (i) { 1063 | point_double(nx, ny, nz, nx, ny, nz); 1064 | } 1065 | table_offset = 0; 1066 | for (j = 0; j <= 32; j += 32) { 1067 | char bit0 = p256_get_bit(scalar, 31 - i + j); 1068 | char bit1 = p256_get_bit(scalar, 95 - i + j); 1069 | char bit2 = p256_get_bit(scalar, 159 - i + j); 1070 | char bit3 = p256_get_bit(scalar, 223 - i + j); 1071 | limb index = bit0 | (bit1 << 1) | (bit2 << 2) | (bit3 << 3); 1072 | 1073 | select_affine_point(px, py, kPrecomputed + table_offset, index); 1074 | table_offset += 30 * NLIMBS; 1075 | 1076 | /* Since scalar is less than the order of the group, we know that 1077 | * {nx,ny,nz} != {px,py,1}, unless both are zero, which we handle 1078 | * below. */ 1079 | point_add_mixed(tx, ty, tz, nx, ny, nz, px, py); 1080 | /* The result of point_add_mixed is incorrect if {nx,ny,nz} is zero 1081 | * (a.k.a. the point at infinity). We handle that situation by 1082 | * copying the point from the table. */ 1083 | copy_conditional(nx, px, n_is_infinity_mask); 1084 | copy_conditional(ny, py, n_is_infinity_mask); 1085 | copy_conditional(nz, kOne, n_is_infinity_mask); 1086 | 1087 | /* Equally, the result is also wrong if the point from the table is 1088 | * zero, which happens when the index is zero. We handle that by 1089 | * only copying from {tx,ty,tz} to {nx,ny,nz} if index != 0. */ 1090 | p_is_noninfinite_mask = NON_ZERO_TO_ALL_ONES(index); 1091 | mask = p_is_noninfinite_mask & ~n_is_infinity_mask; 1092 | copy_conditional(nx, tx, mask); 1093 | copy_conditional(ny, ty, mask); 1094 | copy_conditional(nz, tz, mask); 1095 | /* If p was not zero, then n is now non-zero. */ 1096 | n_is_infinity_mask &= ~p_is_noninfinite_mask; 1097 | } 1098 | } 1099 | } 1100 | 1101 | /* point_to_affine converts a Jacobian point to an affine point. If the input 1102 | * is the point at infinity then it returns (0, 0) in constant time. */ 1103 | static void point_to_affine(felem x_out, felem y_out, const felem nx, 1104 | const felem ny, const felem nz) { 1105 | felem z_inv, z_inv_sq; 1106 | felem_inv(z_inv, nz); 1107 | felem_square(z_inv_sq, z_inv); 1108 | felem_mul(x_out, nx, z_inv_sq); 1109 | felem_mul(z_inv, z_inv, z_inv_sq); 1110 | felem_mul(y_out, ny, z_inv); 1111 | } 1112 | 1113 | /* scalar_base_mult sets {nx,ny,nz} = scalar*{x,y}. */ 1114 | static void scalar_mult(felem nx, felem ny, felem nz, const felem x, 1115 | const felem y, const p256_int* scalar) { 1116 | int i; 1117 | felem px, py, pz, tx, ty, tz; 1118 | felem precomp[16][3]; 1119 | limb n_is_infinity_mask, index, p_is_noninfinite_mask, mask; 1120 | 1121 | /* We precompute 0,1,2,... times {x,y}. */ 1122 | memset(precomp, 0, sizeof(felem) * 3); 1123 | memcpy(&precomp[1][0], x, sizeof(felem)); 1124 | memcpy(&precomp[1][1], y, sizeof(felem)); 1125 | memcpy(&precomp[1][2], kOne, sizeof(felem)); 1126 | 1127 | for (i = 2; i < 16; i += 2) { 1128 | point_double(precomp[i][0], precomp[i][1], precomp[i][2], 1129 | precomp[i / 2][0], precomp[i / 2][1], precomp[i / 2][2]); 1130 | 1131 | point_add_mixed(precomp[i + 1][0], precomp[i + 1][1], precomp[i + 1][2], 1132 | precomp[i][0], precomp[i][1], precomp[i][2], x, y); 1133 | } 1134 | 1135 | memset(nx, 0, sizeof(felem)); 1136 | memset(ny, 0, sizeof(felem)); 1137 | memset(nz, 0, sizeof(felem)); 1138 | n_is_infinity_mask = -1; 1139 | 1140 | /* We add in a window of four bits each iteration and do this 64 times. */ 1141 | for (i = 0; i < 256; i += 4) { 1142 | if (i) { 1143 | point_double(nx, ny, nz, nx, ny, nz); 1144 | point_double(nx, ny, nz, nx, ny, nz); 1145 | point_double(nx, ny, nz, nx, ny, nz); 1146 | point_double(nx, ny, nz, nx, ny, nz); 1147 | } 1148 | 1149 | index = (p256_get_bit(scalar, 255 - i - 0) << 3) | 1150 | (p256_get_bit(scalar, 255 - i - 1) << 2) | 1151 | (p256_get_bit(scalar, 255 - i - 2) << 1) | 1152 | p256_get_bit(scalar, 255 - i - 3); 1153 | 1154 | /* See the comments in scalar_base_mult about handling infinities. */ 1155 | select_jacobian_point(px, py, pz, precomp[0][0], index); 1156 | point_add(tx, ty, tz, nx, ny, nz, px, py, pz); 1157 | copy_conditional(nx, px, n_is_infinity_mask); 1158 | copy_conditional(ny, py, n_is_infinity_mask); 1159 | copy_conditional(nz, pz, n_is_infinity_mask); 1160 | 1161 | p_is_noninfinite_mask = NON_ZERO_TO_ALL_ONES(index); 1162 | mask = p_is_noninfinite_mask & ~n_is_infinity_mask; 1163 | 1164 | copy_conditional(nx, tx, mask); 1165 | copy_conditional(ny, ty, mask); 1166 | copy_conditional(nz, tz, mask); 1167 | n_is_infinity_mask &= ~p_is_noninfinite_mask; 1168 | } 1169 | } 1170 | 1171 | #define kRDigits {2, 0, 0, 0xfffffffe, 0xffffffff, 0xffffffff, 0xfffffffd, 1} // 2^257 mod p256.p 1172 | 1173 | #define kRInvDigits {0x80000000, 1, 0xffffffff, 0, 0x80000001, 0xfffffffe, 1, 0x7fffffff} // 1 / 2^257 mod p256.p 1174 | 1175 | static const p256_int kR = { kRDigits }; 1176 | static const p256_int kRInv = { kRInvDigits }; 1177 | 1178 | /* to_montgomery sets out = R*in. */ 1179 | static void to_montgomery(felem out, const p256_int* in) { 1180 | p256_int in_shifted; 1181 | int i; 1182 | 1183 | p256_init(&in_shifted); 1184 | p256_modmul(&SECP256r1_p, in, 0, &kR, &in_shifted); 1185 | 1186 | for (i = 0; i < NLIMBS; i++) { 1187 | if ((i & 1) == 0) { 1188 | out[i] = P256_DIGIT(&in_shifted, 0) & kBottom29Bits; 1189 | p256_shr(&in_shifted, 29, &in_shifted); 1190 | } else { 1191 | out[i] = P256_DIGIT(&in_shifted, 0) & kBottom28Bits; 1192 | p256_shr(&in_shifted, 28, &in_shifted); 1193 | } 1194 | } 1195 | 1196 | p256_clear(&in_shifted); 1197 | } 1198 | 1199 | /* from_montgomery sets out=in/R. */ 1200 | static void from_montgomery(p256_int* out, const felem in) { 1201 | p256_int result, tmp; 1202 | int i, top; 1203 | 1204 | p256_init(&result); 1205 | p256_init(&tmp); 1206 | 1207 | p256_add_d(&tmp, in[NLIMBS - 1], &result); 1208 | for (i = NLIMBS - 2; i >= 0; i--) { 1209 | if ((i & 1) == 0) { 1210 | top = p256_shl(&result, 29, &tmp); 1211 | } else { 1212 | top = p256_shl(&result, 28, &tmp); 1213 | } 1214 | top |= p256_add_d(&tmp, in[i], &result); 1215 | } 1216 | 1217 | p256_modmul(&SECP256r1_p, &kRInv, top, &result, out); 1218 | 1219 | p256_clear(&result); 1220 | p256_clear(&tmp); 1221 | } 1222 | 1223 | /* p256_base_point_mul sets {out_x,out_y} = nG, where n is < the 1224 | * order of the group. */ 1225 | void p256_base_point_mul(const p256_int* n, p256_int* out_x, p256_int* out_y) { 1226 | felem x, y, z; 1227 | 1228 | scalar_base_mult(x, y, z, n); 1229 | 1230 | { 1231 | felem x_affine, y_affine; 1232 | 1233 | point_to_affine(x_affine, y_affine, x, y, z); 1234 | from_montgomery(out_x, x_affine); 1235 | from_montgomery(out_y, y_affine); 1236 | } 1237 | } 1238 | 1239 | /* p256_points_mul_vartime sets {out_x,out_y} = n1*G + n2*{in_x,in_y}, where 1240 | * n1 and n2 are < the order of the group. 1241 | * 1242 | * As indicated by the name, this function operates in variable time. This 1243 | * is safe because it's used for signature validation which doesn't deal 1244 | * with secrets. */ 1245 | void p256_points_mul_vartime( 1246 | const p256_int* n1, const p256_int* n2, const p256_int* in_x, 1247 | const p256_int* in_y, p256_int* out_x, p256_int* out_y) { 1248 | felem x1, y1, z1, x2, y2, z2, px, py; 1249 | 1250 | /* If both scalars are zero, then the result is the point at infinity. */ 1251 | if (p256_is_zero(n1) != 0 && p256_is_zero(n2) != 0) { 1252 | p256_clear(out_x); 1253 | p256_clear(out_y); 1254 | return; 1255 | } 1256 | 1257 | to_montgomery(px, in_x); 1258 | to_montgomery(py, in_y); 1259 | scalar_base_mult(x1, y1, z1, n1); 1260 | scalar_mult(x2, y2, z2, px, py, n2); 1261 | 1262 | if (p256_is_zero(n2) != 0) { 1263 | /* If n2 == 0, then {x2,y2,z2} is zero and the result is just 1264 | * {x1,y1,z1}. */ 1265 | } else if (p256_is_zero(n1) != 0) { 1266 | /* If n1 == 0, then {x1,y1,z1} is zero and the result is just 1267 | * {x2,y2,z2}. */ 1268 | memcpy(x1, x2, sizeof(x2)); 1269 | memcpy(y1, y2, sizeof(y2)); 1270 | memcpy(z1, z2, sizeof(z2)); 1271 | } else { 1272 | /* This function handles the case where {x1,y1,z1} == {x2,y2,z2}. */ 1273 | point_add_or_double_vartime(x1, y1, z1, x1, y1, z1, x2, y2, z2); 1274 | } 1275 | 1276 | point_to_affine(px, py, x1, y1, z1); 1277 | from_montgomery(out_x, px); 1278 | from_montgomery(out_y, py); 1279 | } 1280 | -------------------------------------------------------------------------------- /libmincrypt/p256_ecdsa.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2013 The Android Open Source Project 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright 7 | * notice, this list of conditions and the following disclaimer. 8 | * * Redistributions in binary form must reproduce the above copyright 9 | * notice, this list of conditions and the following disclaimer in the 10 | * documentation and/or other materials provided with the distribution. 11 | * * Neither the name of Google Inc. nor the names of its contributors may 12 | * be used to endorse or promote products derived from this software 13 | * without specific prior written permission. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY Google Inc. ``AS IS'' AND ANY EXPRESS OR 16 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 17 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 18 | * EVENT SHALL Google Inc. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 19 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 20 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 21 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 22 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 23 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 24 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | 27 | #include 28 | 29 | #include "mincrypt/p256_ecdsa.h" 30 | #include "mincrypt/p256.h" 31 | 32 | int p256_ecdsa_verify(const p256_int* key_x, const p256_int* key_y, 33 | const p256_int* message, 34 | const p256_int* r, const p256_int* s) { 35 | p256_int u, v; 36 | 37 | // Check public key. 38 | if (!p256_is_valid_point(key_x, key_y)) return 0; 39 | 40 | // Check r and s are != 0 % n. 41 | p256_mod(&SECP256r1_n, r, &u); 42 | p256_mod(&SECP256r1_n, s, &v); 43 | if (p256_is_zero(&u) || p256_is_zero(&v)) return 0; 44 | 45 | p256_modinv_vartime(&SECP256r1_n, s, &v); 46 | p256_modmul(&SECP256r1_n, message, 0, &v, &u); // message / s % n 47 | p256_modmul(&SECP256r1_n, r, 0, &v, &v); // r / s % n 48 | 49 | p256_points_mul_vartime(&u, &v, 50 | key_x, key_y, 51 | &u, &v); 52 | 53 | p256_mod(&SECP256r1_n, &u, &u); // (x coord % p) % n 54 | return p256_cmp(r, &u) == 0; 55 | } 56 | 57 | -------------------------------------------------------------------------------- /libmincrypt/rsa.c: -------------------------------------------------------------------------------- 1 | /* rsa.c 2 | ** 3 | ** Copyright 2012, The Android Open Source Project 4 | ** 5 | ** Redistribution and use in source and binary forms, with or without 6 | ** modification, are permitted provided that the following conditions are met: 7 | ** * Redistributions of source code must retain the above copyright 8 | ** notice, this list of conditions and the following disclaimer. 9 | ** * Redistributions in binary form must reproduce the above copyright 10 | ** notice, this list of conditions and the following disclaimer in the 11 | ** documentation and/or other materials provided with the distribution. 12 | ** * Neither the name of Google Inc. nor the names of its contributors may 13 | ** be used to endorse or promote products derived from this software 14 | ** without specific prior written permission. 15 | ** 16 | ** THIS SOFTWARE IS PROVIDED BY Google Inc. ``AS IS'' AND ANY EXPRESS OR 17 | ** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 18 | ** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 19 | ** EVENT SHALL Google Inc. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 | ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 21 | ** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 22 | ** OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 23 | ** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 24 | ** OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 25 | ** ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #include "mincrypt/rsa.h" 29 | #include "mincrypt/sha.h" 30 | #include "mincrypt/sha256.h" 31 | 32 | // a[] -= mod 33 | static void subM(const RSAPublicKey* key, 34 | uint32_t* a) { 35 | int64_t A = 0; 36 | int i; 37 | for (i = 0; i < key->len; ++i) { 38 | A += (uint64_t)a[i] - key->n[i]; 39 | a[i] = (uint32_t)A; 40 | A >>= 32; 41 | } 42 | } 43 | 44 | // return a[] >= mod 45 | static int geM(const RSAPublicKey* key, 46 | const uint32_t* a) { 47 | int i; 48 | for (i = key->len; i;) { 49 | --i; 50 | if (a[i] < key->n[i]) return 0; 51 | if (a[i] > key->n[i]) return 1; 52 | } 53 | return 1; // equal 54 | } 55 | 56 | // montgomery c[] += a * b[] / R % mod 57 | static void montMulAdd(const RSAPublicKey* key, 58 | uint32_t* c, 59 | const uint32_t a, 60 | const uint32_t* b) { 61 | uint64_t A = (uint64_t)a * b[0] + c[0]; 62 | uint32_t d0 = (uint32_t)A * key->n0inv; 63 | uint64_t B = (uint64_t)d0 * key->n[0] + (uint32_t)A; 64 | int i; 65 | 66 | for (i = 1; i < key->len; ++i) { 67 | A = (A >> 32) + (uint64_t)a * b[i] + c[i]; 68 | B = (B >> 32) + (uint64_t)d0 * key->n[i] + (uint32_t)A; 69 | c[i - 1] = (uint32_t)B; 70 | } 71 | 72 | A = (A >> 32) + (B >> 32); 73 | 74 | c[i - 1] = (uint32_t)A; 75 | 76 | if (A >> 32) { 77 | subM(key, c); 78 | } 79 | } 80 | 81 | // montgomery c[] = a[] * b[] / R % mod 82 | static void montMul(const RSAPublicKey* key, 83 | uint32_t* c, 84 | const uint32_t* a, 85 | const uint32_t* b) { 86 | int i; 87 | for (i = 0; i < key->len; ++i) { 88 | c[i] = 0; 89 | } 90 | for (i = 0; i < key->len; ++i) { 91 | montMulAdd(key, c, a[i], b); 92 | } 93 | } 94 | 95 | // In-place public exponentiation. 96 | // Input and output big-endian byte array in inout. 97 | static void modpow(const RSAPublicKey* key, 98 | uint8_t* inout) { 99 | uint32_t a[RSANUMWORDS]; 100 | uint32_t aR[RSANUMWORDS]; 101 | uint32_t aaR[RSANUMWORDS]; 102 | uint32_t* aaa = 0; 103 | int i; 104 | 105 | // Convert from big endian byte array to little endian word array. 106 | for (i = 0; i < key->len; ++i) { 107 | uint32_t tmp = 108 | (inout[((key->len - 1 - i) * 4) + 0] << 24) | 109 | (inout[((key->len - 1 - i) * 4) + 1] << 16) | 110 | (inout[((key->len - 1 - i) * 4) + 2] << 8) | 111 | (inout[((key->len - 1 - i) * 4) + 3] << 0); 112 | a[i] = tmp; 113 | } 114 | 115 | if (key->exponent == 65537) { 116 | aaa = aaR; // Re-use location. 117 | montMul(key, aR, a, key->rr); // aR = a * RR / R mod M 118 | for (i = 0; i < 16; i += 2) { 119 | montMul(key, aaR, aR, aR); // aaR = aR * aR / R mod M 120 | montMul(key, aR, aaR, aaR); // aR = aaR * aaR / R mod M 121 | } 122 | montMul(key, aaa, aR, a); // aaa = aR * a / R mod M 123 | } else if (key->exponent == 3) { 124 | aaa = aR; // Re-use location. 125 | montMul(key, aR, a, key->rr); /* aR = a * RR / R mod M */ 126 | montMul(key, aaR, aR, aR); /* aaR = aR * aR / R mod M */ 127 | montMul(key, aaa, aaR, a); /* aaa = aaR * a / R mod M */ 128 | } 129 | 130 | // Make sure aaa < mod; aaa is at most 1x mod too large. 131 | if (geM(key, aaa)) { 132 | subM(key, aaa); 133 | } 134 | 135 | // Convert to bigendian byte array 136 | for (i = key->len - 1; i >= 0; --i) { 137 | uint32_t tmp = aaa[i]; 138 | *inout++ = tmp >> 24; 139 | *inout++ = tmp >> 16; 140 | *inout++ = tmp >> 8; 141 | *inout++ = tmp >> 0; 142 | } 143 | } 144 | 145 | // Expected PKCS1.5 signature padding bytes, for a keytool RSA signature. 146 | // Has the 0-length optional parameter encoded in the ASN1 (as opposed to the 147 | // other flavor which omits the optional parameter entirely). This code does not 148 | // accept signatures without the optional parameter. 149 | 150 | /* 151 | static const uint8_t sha_padding[RSANUMBYTES] = { 152 | 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 153 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 154 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 155 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 156 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 157 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 158 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 159 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 160 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 161 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 162 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 163 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 164 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 165 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 166 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 167 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 168 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 169 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 170 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 171 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 172 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 173 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 174 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 175 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 176 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 177 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 178 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 179 | 0xff, 0xff, 0xff, 0xff, 0x00, 0x30, 0x21, 0x30, 180 | 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 181 | 0x05, 0x00, 0x04, 0x14, 182 | 183 | // 20 bytes of hash go here. 184 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 185 | }; 186 | */ 187 | 188 | // SHA-1 of PKCS1.5 signature sha_padding for 2048 bit, as above. 189 | // At the location of the bytes of the hash all 00 are hashed. 190 | static const uint8_t kExpectedPadShaRsa2048[SHA_DIGEST_SIZE] = { 191 | 0xdc, 0xbd, 0xbe, 0x42, 0xd5, 0xf5, 0xa7, 0x2e, 192 | 0x6e, 0xfc, 0xf5, 0x5d, 0xaf, 0x9d, 0xea, 0x68, 193 | 0x7c, 0xfb, 0xf1, 0x67 194 | }; 195 | 196 | /* 197 | static const uint8_t sha256_padding[RSANUMBYTES] = { 198 | 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 199 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 200 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 201 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 202 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 203 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 204 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 205 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 206 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 207 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 208 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 209 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 210 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 211 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 212 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 213 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 214 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 215 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 216 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 217 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 218 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 219 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 220 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 221 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 222 | 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 223 | 0xff, 0xff, 0xff, 0xff, 0x00, 0x30, 0x31, 0x30, 224 | 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 225 | 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20, 226 | 227 | // 32 bytes of hash go here. 228 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 229 | 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 230 | }; 231 | */ 232 | 233 | // SHA-256 of PKCS1.5 signature sha256_padding for 2048 bit, as above. 234 | // At the location of the bytes of the hash all 00 are hashed. 235 | static const uint8_t kExpectedPadSha256Rsa2048[SHA256_DIGEST_SIZE] = { 236 | 0xab, 0x28, 0x8d, 0x8a, 0xd7, 0xd9, 0x59, 0x92, 237 | 0xba, 0xcc, 0xf8, 0x67, 0x20, 0xe1, 0x15, 0x2e, 238 | 0x39, 0x8d, 0x80, 0x36, 0xd6, 0x6f, 0xf0, 0xfd, 239 | 0x90, 0xe8, 0x7d, 0x8b, 0xe1, 0x7c, 0x87, 0x59, 240 | }; 241 | 242 | // Verify a 2048-bit RSA PKCS1.5 signature against an expected hash. 243 | // Both e=3 and e=65537 are supported. hash_len may be 244 | // SHA_DIGEST_SIZE (== 20) to indicate a SHA-1 hash, or 245 | // SHA256_DIGEST_SIZE (== 32) to indicate a SHA-256 hash. No other 246 | // values are supported. 247 | // 248 | // Returns 1 on successful verification, 0 on failure. 249 | int RSA_verify(const RSAPublicKey *key, 250 | const uint8_t *signature, 251 | const int len, 252 | const uint8_t *hash, 253 | const int hash_len) { 254 | uint8_t buf[RSANUMBYTES]; 255 | int i; 256 | const uint8_t* padding_hash; 257 | 258 | if (key->len != RSANUMWORDS) { 259 | return 0; // Wrong key passed in. 260 | } 261 | 262 | if (len != sizeof(buf)) { 263 | return 0; // Wrong input length. 264 | } 265 | 266 | if (hash_len != SHA_DIGEST_SIZE && 267 | hash_len != SHA256_DIGEST_SIZE) { 268 | return 0; // Unsupported hash. 269 | } 270 | 271 | if (key->exponent != 3 && key->exponent != 65537) { 272 | return 0; // Unsupported exponent. 273 | } 274 | 275 | for (i = 0; i < len; ++i) { // Copy input to local workspace. 276 | buf[i] = signature[i]; 277 | } 278 | 279 | modpow(key, buf); // In-place exponentiation. 280 | 281 | // Xor sha portion, so it all becomes 00 iff equal. 282 | for (i = len - hash_len; i < len; ++i) { 283 | buf[i] ^= *hash++; 284 | } 285 | 286 | // Hash resulting buf, in-place. 287 | switch (hash_len) { 288 | case SHA_DIGEST_SIZE: 289 | padding_hash = kExpectedPadShaRsa2048; 290 | SHA_hash(buf, len, buf); 291 | break; 292 | case SHA256_DIGEST_SIZE: 293 | padding_hash = kExpectedPadSha256Rsa2048; 294 | SHA256_hash(buf, len, buf); 295 | break; 296 | default: 297 | return 0; 298 | } 299 | 300 | // Compare against expected hash value. 301 | for (i = 0; i < hash_len; ++i) { 302 | if (buf[i] != padding_hash[i]) { 303 | return 0; 304 | } 305 | } 306 | 307 | return 1; // All checked out OK. 308 | } 309 | -------------------------------------------------------------------------------- /libmincrypt/sha.c: -------------------------------------------------------------------------------- 1 | /* sha.c 2 | ** 3 | ** Copyright 2013, The Android Open Source Project 4 | ** 5 | ** Redistribution and use in source and binary forms, with or without 6 | ** modification, are permitted provided that the following conditions are met: 7 | ** * Redistributions of source code must retain the above copyright 8 | ** notice, this list of conditions and the following disclaimer. 9 | ** * Redistributions in binary form must reproduce the above copyright 10 | ** notice, this list of conditions and the following disclaimer in the 11 | ** documentation and/or other materials provided with the distribution. 12 | ** * Neither the name of Google Inc. nor the names of its contributors may 13 | ** be used to endorse or promote products derived from this software 14 | ** without specific prior written permission. 15 | ** 16 | ** THIS SOFTWARE IS PROVIDED BY Google Inc. ``AS IS'' AND ANY EXPRESS OR 17 | ** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 18 | ** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 19 | ** EVENT SHALL Google Inc. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 | ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 21 | ** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 22 | ** OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 23 | ** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 24 | ** OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 25 | ** ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | // Optimized for minimal code size. 29 | 30 | #include "mincrypt/sha.h" 31 | 32 | #include 33 | #include 34 | #include 35 | 36 | #define rol(bits, value) (((value) << (bits)) | ((value) >> (32 - (bits)))) 37 | 38 | static void SHA1_Transform(SHA_CTX* ctx) { 39 | uint32_t W[80]; 40 | uint32_t A, B, C, D, E; 41 | uint8_t* p = ctx->buf; 42 | int t; 43 | 44 | for(t = 0; t < 16; ++t) { 45 | uint32_t tmp = *p++ << 24; 46 | tmp |= *p++ << 16; 47 | tmp |= *p++ << 8; 48 | tmp |= *p++; 49 | W[t] = tmp; 50 | } 51 | 52 | for(; t < 80; t++) { 53 | W[t] = rol(1,W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]); 54 | } 55 | 56 | A = ctx->state[0]; 57 | B = ctx->state[1]; 58 | C = ctx->state[2]; 59 | D = ctx->state[3]; 60 | E = ctx->state[4]; 61 | 62 | for(t = 0; t < 80; t++) { 63 | uint32_t tmp = rol(5,A) + E + W[t]; 64 | 65 | if (t < 20) 66 | tmp += (D^(B&(C^D))) + 0x5A827999; 67 | else if ( t < 40) 68 | tmp += (B^C^D) + 0x6ED9EBA1; 69 | else if ( t < 60) 70 | tmp += ((B&C)|(D&(B|C))) + 0x8F1BBCDC; 71 | else 72 | tmp += (B^C^D) + 0xCA62C1D6; 73 | 74 | E = D; 75 | D = C; 76 | C = rol(30,B); 77 | B = A; 78 | A = tmp; 79 | } 80 | 81 | ctx->state[0] += A; 82 | ctx->state[1] += B; 83 | ctx->state[2] += C; 84 | ctx->state[3] += D; 85 | ctx->state[4] += E; 86 | } 87 | 88 | static const HASH_VTAB SHA_VTAB = { 89 | SHA_init, 90 | SHA_update, 91 | SHA_final, 92 | SHA_hash, 93 | SHA_DIGEST_SIZE 94 | }; 95 | 96 | void SHA_init(SHA_CTX* ctx) { 97 | ctx->f = &SHA_VTAB; 98 | ctx->state[0] = 0x67452301; 99 | ctx->state[1] = 0xEFCDAB89; 100 | ctx->state[2] = 0x98BADCFE; 101 | ctx->state[3] = 0x10325476; 102 | ctx->state[4] = 0xC3D2E1F0; 103 | ctx->count = 0; 104 | } 105 | 106 | 107 | void SHA_update(SHA_CTX* ctx, const void* data, int len) { 108 | int i = (int) (ctx->count & 63); 109 | const uint8_t* p = (const uint8_t*)data; 110 | 111 | ctx->count += len; 112 | 113 | while (len--) { 114 | ctx->buf[i++] = *p++; 115 | if (i == 64) { 116 | SHA1_Transform(ctx); 117 | i = 0; 118 | } 119 | } 120 | } 121 | 122 | 123 | const uint8_t* SHA_final(SHA_CTX* ctx) { 124 | uint8_t *p = ctx->buf; 125 | uint64_t cnt = ctx->count * 8; 126 | int i; 127 | 128 | SHA_update(ctx, (uint8_t*)"\x80", 1); 129 | while ((ctx->count & 63) != 56) { 130 | SHA_update(ctx, (uint8_t*)"\0", 1); 131 | } 132 | for (i = 0; i < 8; ++i) { 133 | uint8_t tmp = (uint8_t) (cnt >> ((7 - i) * 8)); 134 | SHA_update(ctx, &tmp, 1); 135 | } 136 | 137 | for (i = 0; i < 5; i++) { 138 | uint32_t tmp = ctx->state[i]; 139 | *p++ = tmp >> 24; 140 | *p++ = tmp >> 16; 141 | *p++ = tmp >> 8; 142 | *p++ = tmp >> 0; 143 | } 144 | 145 | return ctx->buf; 146 | } 147 | 148 | /* Convenience function */ 149 | const uint8_t* SHA_hash(const void* data, int len, uint8_t* digest) { 150 | SHA_CTX ctx; 151 | SHA_init(&ctx); 152 | SHA_update(&ctx, data, len); 153 | memcpy(digest, SHA_final(&ctx), SHA_DIGEST_SIZE); 154 | return digest; 155 | } 156 | -------------------------------------------------------------------------------- /libmincrypt/sha256.c: -------------------------------------------------------------------------------- 1 | /* sha256.c 2 | ** 3 | ** Copyright 2013, The Android Open Source Project 4 | ** 5 | ** Redistribution and use in source and binary forms, with or without 6 | ** modification, are permitted provided that the following conditions are met: 7 | ** * Redistributions of source code must retain the above copyright 8 | ** notice, this list of conditions and the following disclaimer. 9 | ** * Redistributions in binary form must reproduce the above copyright 10 | ** notice, this list of conditions and the following disclaimer in the 11 | ** documentation and/or other materials provided with the distribution. 12 | ** * Neither the name of Google Inc. nor the names of its contributors may 13 | ** be used to endorse or promote products derived from this software 14 | ** without specific prior written permission. 15 | ** 16 | ** THIS SOFTWARE IS PROVIDED BY Google Inc. ``AS IS'' AND ANY EXPRESS OR 17 | ** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 18 | ** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 19 | ** EVENT SHALL Google Inc. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 | ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 21 | ** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 22 | ** OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 23 | ** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 24 | ** OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 25 | ** ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | // Optimized for minimal code size. 29 | 30 | #include "mincrypt/sha256.h" 31 | 32 | #include 33 | #include 34 | #include 35 | 36 | #define ror(value, bits) (((value) >> (bits)) | ((value) << (32 - (bits)))) 37 | #define shr(value, bits) ((value) >> (bits)) 38 | 39 | static const uint32_t K[64] = { 40 | 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 41 | 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, 42 | 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 43 | 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 44 | 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 45 | 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 46 | 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 47 | 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, 48 | 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 49 | 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 50 | 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 51 | 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, 52 | 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 53 | 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, 54 | 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 55 | 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 }; 56 | 57 | static void SHA256_Transform(SHA256_CTX* ctx) { 58 | uint32_t W[64]; 59 | uint32_t A, B, C, D, E, F, G, H; 60 | uint8_t* p = ctx->buf; 61 | int t; 62 | 63 | for(t = 0; t < 16; ++t) { 64 | uint32_t tmp = *p++ << 24; 65 | tmp |= *p++ << 16; 66 | tmp |= *p++ << 8; 67 | tmp |= *p++; 68 | W[t] = tmp; 69 | } 70 | 71 | for(; t < 64; t++) { 72 | uint32_t s0 = ror(W[t-15], 7) ^ ror(W[t-15], 18) ^ shr(W[t-15], 3); 73 | uint32_t s1 = ror(W[t-2], 17) ^ ror(W[t-2], 19) ^ shr(W[t-2], 10); 74 | W[t] = W[t-16] + s0 + W[t-7] + s1; 75 | } 76 | 77 | A = ctx->state[0]; 78 | B = ctx->state[1]; 79 | C = ctx->state[2]; 80 | D = ctx->state[3]; 81 | E = ctx->state[4]; 82 | F = ctx->state[5]; 83 | G = ctx->state[6]; 84 | H = ctx->state[7]; 85 | 86 | for(t = 0; t < 64; t++) { 87 | uint32_t s0 = ror(A, 2) ^ ror(A, 13) ^ ror(A, 22); 88 | uint32_t maj = (A & B) ^ (A & C) ^ (B & C); 89 | uint32_t t2 = s0 + maj; 90 | uint32_t s1 = ror(E, 6) ^ ror(E, 11) ^ ror(E, 25); 91 | uint32_t ch = (E & F) ^ ((~E) & G); 92 | uint32_t t1 = H + s1 + ch + K[t] + W[t]; 93 | 94 | H = G; 95 | G = F; 96 | F = E; 97 | E = D + t1; 98 | D = C; 99 | C = B; 100 | B = A; 101 | A = t1 + t2; 102 | } 103 | 104 | ctx->state[0] += A; 105 | ctx->state[1] += B; 106 | ctx->state[2] += C; 107 | ctx->state[3] += D; 108 | ctx->state[4] += E; 109 | ctx->state[5] += F; 110 | ctx->state[6] += G; 111 | ctx->state[7] += H; 112 | } 113 | 114 | static const HASH_VTAB SHA256_VTAB = { 115 | SHA256_init, 116 | SHA256_update, 117 | SHA256_final, 118 | SHA256_hash, 119 | SHA256_DIGEST_SIZE 120 | }; 121 | 122 | void SHA256_init(SHA256_CTX* ctx) { 123 | ctx->f = &SHA256_VTAB; 124 | ctx->state[0] = 0x6a09e667; 125 | ctx->state[1] = 0xbb67ae85; 126 | ctx->state[2] = 0x3c6ef372; 127 | ctx->state[3] = 0xa54ff53a; 128 | ctx->state[4] = 0x510e527f; 129 | ctx->state[5] = 0x9b05688c; 130 | ctx->state[6] = 0x1f83d9ab; 131 | ctx->state[7] = 0x5be0cd19; 132 | ctx->count = 0; 133 | } 134 | 135 | 136 | void SHA256_update(SHA256_CTX* ctx, const void* data, int len) { 137 | int i = (int) (ctx->count & 63); 138 | const uint8_t* p = (const uint8_t*)data; 139 | 140 | ctx->count += len; 141 | 142 | while (len--) { 143 | ctx->buf[i++] = *p++; 144 | if (i == 64) { 145 | SHA256_Transform(ctx); 146 | i = 0; 147 | } 148 | } 149 | } 150 | 151 | 152 | const uint8_t* SHA256_final(SHA256_CTX* ctx) { 153 | uint8_t *p = ctx->buf; 154 | uint64_t cnt = ctx->count * 8; 155 | int i; 156 | 157 | SHA256_update(ctx, (uint8_t*)"\x80", 1); 158 | while ((ctx->count & 63) != 56) { 159 | SHA256_update(ctx, (uint8_t*)"\0", 1); 160 | } 161 | for (i = 0; i < 8; ++i) { 162 | uint8_t tmp = (uint8_t) (cnt >> ((7 - i) * 8)); 163 | SHA256_update(ctx, &tmp, 1); 164 | } 165 | 166 | for (i = 0; i < 8; i++) { 167 | uint32_t tmp = ctx->state[i]; 168 | *p++ = tmp >> 24; 169 | *p++ = tmp >> 16; 170 | *p++ = tmp >> 8; 171 | *p++ = tmp >> 0; 172 | } 173 | 174 | return ctx->buf; 175 | } 176 | 177 | /* Convenience function */ 178 | const uint8_t* SHA256_hash(const void* data, int len, uint8_t* digest) { 179 | SHA256_CTX ctx; 180 | SHA256_init(&ctx); 181 | SHA256_update(&ctx, data, len); 182 | memcpy(digest, SHA256_final(&ctx), SHA256_DIGEST_SIZE); 183 | return digest; 184 | } 185 | -------------------------------------------------------------------------------- /mincrypt/dsa_sig.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2013 The Android Open Source Project 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright 7 | * notice, this list of conditions and the following disclaimer. 8 | * * Redistributions in binary form must reproduce the above copyright 9 | * notice, this list of conditions and the following disclaimer in the 10 | * documentation and/or other materials provided with the distribution. 11 | * * Neither the name of Google Inc. nor the names of its contributors may 12 | * be used to endorse or promote products derived from this software 13 | * without specific prior written permission. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY Google Inc. ``AS IS'' AND ANY EXPRESS OR 16 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 17 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 18 | * EVENT SHALL Google Inc. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 19 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 20 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 21 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 22 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 23 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 24 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | 27 | #ifndef SYSTEM_CORE_INCLUDE_MINCRYPT_DSA_SIG_H_ 28 | #define SYSTEM_CORE_INCLUDE_MINCRYPT_DSA_SIG_H_ 29 | 30 | #include "mincrypt/p256.h" 31 | 32 | #ifdef __cplusplus 33 | extern "C" { 34 | #endif 35 | 36 | // Returns 0 if input sig is not a valid ASN.1 sequence 37 | int dsa_sig_unpack(unsigned char* sig, int sig_len, p256_int* r_int, p256_int* s_int); 38 | 39 | #ifdef __cplusplus 40 | } 41 | #endif 42 | 43 | #endif /* SYSTEM_CORE_INCLUDE_MINCRYPT_DSA_SIG_H_ */ 44 | -------------------------------------------------------------------------------- /mincrypt/hash-internal.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2007 The Android Open Source Project 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright 7 | * notice, this list of conditions and the following disclaimer. 8 | * * Redistributions in binary form must reproduce the above copyright 9 | * notice, this list of conditions and the following disclaimer in the 10 | * documentation and/or other materials provided with the distribution. 11 | * * Neither the name of Google Inc. nor the names of its contributors may 12 | * be used to endorse or promote products derived from this software 13 | * without specific prior written permission. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY Google Inc. ``AS IS'' AND ANY EXPRESS OR 16 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 17 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 18 | * EVENT SHALL Google Inc. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 19 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 20 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 21 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 22 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 23 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 24 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | 27 | #ifndef SYSTEM_CORE_INCLUDE_MINCRYPT_HASH_INTERNAL_H_ 28 | #define SYSTEM_CORE_INCLUDE_MINCRYPT_HASH_INTERNAL_H_ 29 | 30 | #include 31 | 32 | #ifdef __cplusplus 33 | extern "C" { 34 | #endif // __cplusplus 35 | 36 | struct HASH_CTX; // forward decl 37 | 38 | typedef struct HASH_VTAB { 39 | void (* const init)(struct HASH_CTX*); 40 | void (* const update)(struct HASH_CTX*, const void*, int); 41 | const uint8_t* (* const final)(struct HASH_CTX*); 42 | const uint8_t* (* const hash)(const void*, int, uint8_t*); 43 | int size; 44 | } HASH_VTAB; 45 | 46 | typedef struct HASH_CTX { 47 | const HASH_VTAB * f; 48 | uint64_t count; 49 | uint8_t buf[64]; 50 | uint32_t state[8]; // upto SHA2 51 | } HASH_CTX; 52 | 53 | #define HASH_init(ctx) (ctx)->f->init(ctx) 54 | #define HASH_update(ctx, data, len) (ctx)->f->update(ctx, data, len) 55 | #define HASH_final(ctx) (ctx)->f->final(ctx) 56 | #define HASH_hash(data, len, digest) (ctx)->f->hash(data, len, digest) 57 | #define HASH_size(ctx) (ctx)->f->size 58 | 59 | #ifdef __cplusplus 60 | } 61 | #endif // __cplusplus 62 | 63 | #endif // SYSTEM_CORE_INCLUDE_MINCRYPT_HASH_INTERNAL_H_ 64 | -------------------------------------------------------------------------------- /mincrypt/p256.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2013 The Android Open Source Project 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright 7 | * notice, this list of conditions and the following disclaimer. 8 | * * Redistributions in binary form must reproduce the above copyright 9 | * notice, this list of conditions and the following disclaimer in the 10 | * documentation and/or other materials provided with the distribution. 11 | * * Neither the name of Google Inc. nor the names of its contributors may 12 | * be used to endorse or promote products derived from this software 13 | * without specific prior written permission. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY Google Inc. ``AS IS'' AND ANY EXPRESS OR 16 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 17 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 18 | * EVENT SHALL Google Inc. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 19 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 20 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 21 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 22 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 23 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 24 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | 27 | #ifndef SYSTEM_CORE_INCLUDE_MINCRYPT_LITE_P256_H_ 28 | #define SYSTEM_CORE_INCLUDE_MINCRYPT_LITE_P256_H_ 29 | 30 | // Collection of routines manipulating 256 bit unsigned integers. 31 | // Just enough to implement ecdsa-p256 and related algorithms. 32 | 33 | #include 34 | 35 | #ifdef __cplusplus 36 | extern "C" { 37 | #endif 38 | 39 | #define P256_BITSPERDIGIT 32 40 | #define P256_NDIGITS 8 41 | #define P256_NBYTES 32 42 | 43 | typedef int p256_err; 44 | typedef uint32_t p256_digit; 45 | typedef int32_t p256_sdigit; 46 | typedef uint64_t p256_ddigit; 47 | typedef int64_t p256_sddigit; 48 | 49 | // Defining p256_int as struct to leverage struct assigment. 50 | typedef struct { 51 | p256_digit a[P256_NDIGITS]; 52 | } p256_int; 53 | 54 | extern const p256_int SECP256r1_n; // Curve order 55 | extern const p256_int SECP256r1_p; // Curve prime 56 | extern const p256_int SECP256r1_b; // Curve param 57 | 58 | // Initialize a p256_int to zero. 59 | void p256_init(p256_int* a); 60 | 61 | // Clear a p256_int to zero. 62 | void p256_clear(p256_int* a); 63 | 64 | // Return bit. Index 0 is least significant. 65 | int p256_get_bit(const p256_int* a, int index); 66 | 67 | // b := a % MOD 68 | void p256_mod( 69 | const p256_int* MOD, 70 | const p256_int* a, 71 | p256_int* b); 72 | 73 | // c := a * (top_b | b) % MOD 74 | void p256_modmul( 75 | const p256_int* MOD, 76 | const p256_int* a, 77 | const p256_digit top_b, 78 | const p256_int* b, 79 | p256_int* c); 80 | 81 | // b := 1 / a % MOD 82 | // MOD best be SECP256r1_n 83 | void p256_modinv( 84 | const p256_int* MOD, 85 | const p256_int* a, 86 | p256_int* b); 87 | 88 | // b := 1 / a % MOD 89 | // MOD best be SECP256r1_n 90 | // Faster than p256_modinv() 91 | void p256_modinv_vartime( 92 | const p256_int* MOD, 93 | const p256_int* a, 94 | p256_int* b); 95 | 96 | // b := a << (n % P256_BITSPERDIGIT) 97 | // Returns the bits shifted out of most significant digit. 98 | p256_digit p256_shl(const p256_int* a, int n, p256_int* b); 99 | 100 | // b := a >> (n % P256_BITSPERDIGIT) 101 | void p256_shr(const p256_int* a, int n, p256_int* b); 102 | 103 | int p256_is_zero(const p256_int* a); 104 | int p256_is_odd(const p256_int* a); 105 | int p256_is_even(const p256_int* a); 106 | 107 | // Returns -1, 0 or 1. 108 | int p256_cmp(const p256_int* a, const p256_int *b); 109 | 110 | // c: = a - b 111 | // Returns -1 on borrow. 112 | int p256_sub(const p256_int* a, const p256_int* b, p256_int* c); 113 | 114 | // c := a + b 115 | // Returns 1 on carry. 116 | int p256_add(const p256_int* a, const p256_int* b, p256_int* c); 117 | 118 | // c := a + (single digit)b 119 | // Returns carry 1 on carry. 120 | int p256_add_d(const p256_int* a, p256_digit b, p256_int* c); 121 | 122 | // ec routines. 123 | 124 | // {out_x,out_y} := nG 125 | void p256_base_point_mul(const p256_int *n, 126 | p256_int *out_x, 127 | p256_int *out_y); 128 | 129 | // {out_x,out_y} := n{in_x,in_y} 130 | void p256_point_mul(const p256_int *n, 131 | const p256_int *in_x, 132 | const p256_int *in_y, 133 | p256_int *out_x, 134 | p256_int *out_y); 135 | 136 | // {out_x,out_y} := n1G + n2{in_x,in_y} 137 | void p256_points_mul_vartime( 138 | const p256_int *n1, const p256_int *n2, 139 | const p256_int *in_x, const p256_int *in_y, 140 | p256_int *out_x, p256_int *out_y); 141 | 142 | // Return whether point {x,y} is on curve. 143 | int p256_is_valid_point(const p256_int* x, const p256_int* y); 144 | 145 | // Outputs big-endian binary form. No leading zero skips. 146 | void p256_to_bin(const p256_int* src, uint8_t dst[P256_NBYTES]); 147 | 148 | // Reads from big-endian binary form, 149 | // thus pre-pad with leading zeros if short. 150 | void p256_from_bin(const uint8_t src[P256_NBYTES], p256_int* dst); 151 | 152 | #define P256_DIGITS(x) ((x)->a) 153 | #define P256_DIGIT(x,y) ((x)->a[y]) 154 | 155 | #define P256_ZERO {{0}} 156 | #define P256_ONE {{1}} 157 | 158 | #ifdef __cplusplus 159 | } 160 | #endif 161 | 162 | #endif // SYSTEM_CORE_INCLUDE_MINCRYPT_LITE_P256_H_ 163 | -------------------------------------------------------------------------------- /mincrypt/p256_ecdsa.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2013 The Android Open Source Project 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright 7 | * notice, this list of conditions and the following disclaimer. 8 | * * Redistributions in binary form must reproduce the above copyright 9 | * notice, this list of conditions and the following disclaimer in the 10 | * documentation and/or other materials provided with the distribution. 11 | * * Neither the name of Google Inc. nor the names of its contributors may 12 | * be used to endorse or promote products derived from this software 13 | * without specific prior written permission. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY Google Inc. ``AS IS'' AND ANY EXPRESS OR 16 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 17 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 18 | * EVENT SHALL Google Inc. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 19 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 20 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 21 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 22 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 23 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 24 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | 27 | #ifndef SYSTEM_CORE_INCLUDE_MINCRYPT_P256_ECDSA_H_ 28 | #define SYSTEM_CORE_INCLUDE_MINCRYPT_P256_ECDSA_H_ 29 | 30 | // Using current directory as relative include path here since 31 | // this code typically gets lifted into a variety of build systems 32 | // and directory structures. 33 | #include "p256.h" 34 | 35 | #ifdef __cplusplus 36 | extern "C" { 37 | #endif 38 | 39 | // Returns 0 if {r,s} is not a signature on message for 40 | // public key {key_x,key_y}. 41 | // 42 | // Note: message is a p256_int. 43 | // Convert from a binary string using p256_from_bin(). 44 | int p256_ecdsa_verify(const p256_int* key_x, 45 | const p256_int* key_y, 46 | const p256_int* message, 47 | const p256_int* r, const p256_int* s); 48 | 49 | #ifdef __cplusplus 50 | } 51 | #endif 52 | 53 | #endif // SYSTEM_CORE_INCLUDE_MINCRYPT_P256_ECDSA_H_ 54 | -------------------------------------------------------------------------------- /mincrypt/rsa.h: -------------------------------------------------------------------------------- 1 | /* rsa.h 2 | ** 3 | ** Copyright 2008, The Android Open Source Project 4 | ** 5 | ** Redistribution and use in source and binary forms, with or without 6 | ** modification, are permitted provided that the following conditions are met: 7 | ** * Redistributions of source code must retain the above copyright 8 | ** notice, this list of conditions and the following disclaimer. 9 | ** * Redistributions in binary form must reproduce the above copyright 10 | ** notice, this list of conditions and the following disclaimer in the 11 | ** documentation and/or other materials provided with the distribution. 12 | ** * Neither the name of Google Inc. nor the names of its contributors may 13 | ** be used to endorse or promote products derived from this software 14 | ** without specific prior written permission. 15 | ** 16 | ** THIS SOFTWARE IS PROVIDED BY Google Inc. ``AS IS'' AND ANY EXPRESS OR 17 | ** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 18 | ** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 19 | ** EVENT SHALL Google Inc. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 | ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 21 | ** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 22 | ** OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 23 | ** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 24 | ** OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 25 | ** ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | #ifndef SYSTEM_CORE_INCLUDE_MINCRYPT_RSA_H_ 29 | #define SYSTEM_CORE_INCLUDE_MINCRYPT_RSA_H_ 30 | 31 | #include 32 | 33 | #ifdef __cplusplus 34 | extern "C" { 35 | #endif 36 | 37 | #define RSANUMBYTES 256 /* 2048 bit key length */ 38 | #define RSANUMWORDS (RSANUMBYTES / sizeof(uint32_t)) 39 | 40 | typedef struct RSAPublicKey { 41 | int len; /* Length of n[] in number of uint32_t */ 42 | uint32_t n0inv; /* -1 / n[0] mod 2^32 */ 43 | uint32_t n[RSANUMWORDS]; /* modulus as little endian array */ 44 | uint32_t rr[RSANUMWORDS]; /* R^2 as little endian array */ 45 | int exponent; /* 3 or 65537 */ 46 | } RSAPublicKey; 47 | 48 | int RSA_verify(const RSAPublicKey *key, 49 | const uint8_t* signature, 50 | const int len, 51 | const uint8_t* hash, 52 | const int hash_len); 53 | 54 | #ifdef __cplusplus 55 | } 56 | #endif 57 | 58 | #endif // SYSTEM_CORE_INCLUDE_MINCRYPT_RSA_H_ 59 | -------------------------------------------------------------------------------- /mincrypt/sha.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2005 The Android Open Source Project 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright 7 | * notice, this list of conditions and the following disclaimer. 8 | * * Redistributions in binary form must reproduce the above copyright 9 | * notice, this list of conditions and the following disclaimer in the 10 | * documentation and/or other materials provided with the distribution. 11 | * * Neither the name of Google Inc. nor the names of its contributors may 12 | * be used to endorse or promote products derived from this software 13 | * without specific prior written permission. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY Google Inc. ``AS IS'' AND ANY EXPRESS OR 16 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 17 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 18 | * EVENT SHALL Google Inc. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 19 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 20 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 21 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 22 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 23 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 24 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | #ifndef SYSTEM_CORE_INCLUDE_MINCRYPT_SHA1_H_ 27 | #define SYSTEM_CORE_INCLUDE_MINCRYPT_SHA1_H_ 28 | 29 | #include 30 | #include "hash-internal.h" 31 | 32 | #ifdef __cplusplus 33 | extern "C" { 34 | #endif // __cplusplus 35 | 36 | typedef HASH_CTX SHA_CTX; 37 | 38 | void SHA_init(SHA_CTX* ctx); 39 | void SHA_update(SHA_CTX* ctx, const void* data, int len); 40 | const uint8_t* SHA_final(SHA_CTX* ctx); 41 | 42 | // Convenience method. Returns digest address. 43 | // NOTE: *digest needs to hold SHA_DIGEST_SIZE bytes. 44 | const uint8_t* SHA_hash(const void* data, int len, uint8_t* digest); 45 | 46 | #define SHA_DIGEST_SIZE 20 47 | 48 | #ifdef __cplusplus 49 | } 50 | #endif // __cplusplus 51 | 52 | #endif // SYSTEM_CORE_INCLUDE_MINCRYPT_SHA1_H_ 53 | -------------------------------------------------------------------------------- /mincrypt/sha256.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2011 The Android Open Source Project 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are met: 6 | * * Redistributions of source code must retain the above copyright 7 | * notice, this list of conditions and the following disclaimer. 8 | * * Redistributions in binary form must reproduce the above copyright 9 | * notice, this list of conditions and the following disclaimer in the 10 | * documentation and/or other materials provided with the distribution. 11 | * * Neither the name of Google Inc. nor the names of its contributors may 12 | * be used to endorse or promote products derived from this software 13 | * without specific prior written permission. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY Google Inc. ``AS IS'' AND ANY EXPRESS OR 16 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 17 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 18 | * EVENT SHALL Google Inc. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 19 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 20 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 21 | * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 22 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 23 | * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 24 | * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | */ 26 | 27 | #ifndef SYSTEM_CORE_INCLUDE_MINCRYPT_SHA256_H_ 28 | #define SYSTEM_CORE_INCLUDE_MINCRYPT_SHA256_H_ 29 | 30 | #include 31 | #include "hash-internal.h" 32 | 33 | #ifdef __cplusplus 34 | extern "C" { 35 | #endif // __cplusplus 36 | 37 | typedef HASH_CTX SHA256_CTX; 38 | 39 | void SHA256_init(SHA256_CTX* ctx); 40 | void SHA256_update(SHA256_CTX* ctx, const void* data, int len); 41 | const uint8_t* SHA256_final(SHA256_CTX* ctx); 42 | 43 | // Convenience method. Returns digest address. 44 | const uint8_t* SHA256_hash(const void* data, int len, uint8_t* digest); 45 | 46 | #define SHA256_DIGEST_SIZE 32 47 | 48 | #ifdef __cplusplus 49 | } 50 | #endif // __cplusplus 51 | 52 | #endif // SYSTEM_CORE_INCLUDE_MINCRYPT_SHA256_H_ 53 | --------------------------------------------------------------------------------