Damien Miller | 3cccc0e | 2013-12-07 11:27:47 +1100 | [diff] [blame] | 1 | /* $OpenBSD: ed25519.c,v 1.2 2013/12/07 00:26:37 djm Exp $ */ |
Damien Miller | 5be9d9e | 2013-12-07 11:24:01 +1100 | [diff] [blame] | 2 | |
| 3 | /* Public Domain, from supercop-20130419/crypto_sign/ed25519/ref/ed25519.c */ |
| 4 | |
Damien Miller | f104da2 | 2013-12-07 12:37:53 +1100 | [diff] [blame] | 5 | #include "includes.h" |
Damien Miller | 5be9d9e | 2013-12-07 11:24:01 +1100 | [diff] [blame] | 6 | #include "crypto_api.h" |
| 7 | |
| 8 | #include "ge25519.h" |
| 9 | |
| 10 | static void get_hram(unsigned char *hram, const unsigned char *sm, const unsigned char *pk, unsigned char *playground, unsigned long long smlen) |
| 11 | { |
| 12 | unsigned long long i; |
| 13 | |
| 14 | for (i = 0;i < 32;++i) playground[i] = sm[i]; |
| 15 | for (i = 32;i < 64;++i) playground[i] = pk[i-32]; |
| 16 | for (i = 64;i < smlen;++i) playground[i] = sm[i]; |
| 17 | |
| 18 | crypto_hash_sha512(hram,playground,smlen); |
| 19 | } |
| 20 | |
| 21 | |
| 22 | int crypto_sign_ed25519_keypair( |
| 23 | unsigned char *pk, |
| 24 | unsigned char *sk |
| 25 | ) |
| 26 | { |
| 27 | sc25519 scsk; |
| 28 | ge25519 gepk; |
| 29 | unsigned char extsk[64]; |
| 30 | int i; |
| 31 | |
| 32 | randombytes(sk, 32); |
| 33 | crypto_hash_sha512(extsk, sk, 32); |
| 34 | extsk[0] &= 248; |
| 35 | extsk[31] &= 127; |
| 36 | extsk[31] |= 64; |
| 37 | |
| 38 | sc25519_from32bytes(&scsk,extsk); |
| 39 | |
| 40 | ge25519_scalarmult_base(&gepk, &scsk); |
| 41 | ge25519_pack(pk, &gepk); |
| 42 | for(i=0;i<32;i++) |
| 43 | sk[32 + i] = pk[i]; |
| 44 | return 0; |
| 45 | } |
| 46 | |
| 47 | int crypto_sign_ed25519( |
| 48 | unsigned char *sm,unsigned long long *smlen, |
| 49 | const unsigned char *m,unsigned long long mlen, |
| 50 | const unsigned char *sk |
| 51 | ) |
| 52 | { |
| 53 | sc25519 sck, scs, scsk; |
| 54 | ge25519 ger; |
| 55 | unsigned char r[32]; |
| 56 | unsigned char s[32]; |
| 57 | unsigned char extsk[64]; |
| 58 | unsigned long long i; |
| 59 | unsigned char hmg[crypto_hash_sha512_BYTES]; |
| 60 | unsigned char hram[crypto_hash_sha512_BYTES]; |
| 61 | |
| 62 | crypto_hash_sha512(extsk, sk, 32); |
| 63 | extsk[0] &= 248; |
| 64 | extsk[31] &= 127; |
| 65 | extsk[31] |= 64; |
| 66 | |
| 67 | *smlen = mlen+64; |
| 68 | for(i=0;i<mlen;i++) |
| 69 | sm[64 + i] = m[i]; |
| 70 | for(i=0;i<32;i++) |
| 71 | sm[32 + i] = extsk[32+i]; |
| 72 | |
| 73 | crypto_hash_sha512(hmg, sm+32, mlen+32); /* Generate k as h(extsk[32],...,extsk[63],m) */ |
| 74 | |
| 75 | /* Computation of R */ |
| 76 | sc25519_from64bytes(&sck, hmg); |
| 77 | ge25519_scalarmult_base(&ger, &sck); |
| 78 | ge25519_pack(r, &ger); |
| 79 | |
| 80 | /* Computation of s */ |
| 81 | for(i=0;i<32;i++) |
| 82 | sm[i] = r[i]; |
| 83 | |
| 84 | get_hram(hram, sm, sk+32, sm, mlen+64); |
| 85 | |
| 86 | sc25519_from64bytes(&scs, hram); |
| 87 | sc25519_from32bytes(&scsk, extsk); |
| 88 | sc25519_mul(&scs, &scs, &scsk); |
| 89 | |
| 90 | sc25519_add(&scs, &scs, &sck); |
| 91 | |
| 92 | sc25519_to32bytes(s,&scs); /* cat s */ |
| 93 | for(i=0;i<32;i++) |
| 94 | sm[32 + i] = s[i]; |
| 95 | |
| 96 | return 0; |
| 97 | } |
| 98 | |
| 99 | int crypto_sign_ed25519_open( |
| 100 | unsigned char *m,unsigned long long *mlen, |
| 101 | const unsigned char *sm,unsigned long long smlen, |
| 102 | const unsigned char *pk |
| 103 | ) |
| 104 | { |
| 105 | unsigned int i; |
| 106 | int ret; |
| 107 | unsigned char t2[32]; |
| 108 | ge25519 get1, get2; |
| 109 | sc25519 schram, scs; |
| 110 | unsigned char hram[crypto_hash_sha512_BYTES]; |
| 111 | |
| 112 | *mlen = (unsigned long long) -1; |
| 113 | if (smlen < 64) return -1; |
| 114 | |
| 115 | if (ge25519_unpackneg_vartime(&get1, pk)) return -1; |
| 116 | |
| 117 | get_hram(hram,sm,pk,m,smlen); |
| 118 | |
| 119 | sc25519_from64bytes(&schram, hram); |
| 120 | |
| 121 | sc25519_from32bytes(&scs, sm+32); |
| 122 | |
| 123 | ge25519_double_scalarmult_vartime(&get2, &get1, &schram, &ge25519_base, &scs); |
| 124 | ge25519_pack(t2, &get2); |
| 125 | |
| 126 | ret = crypto_verify_32(sm, t2); |
| 127 | |
| 128 | if (!ret) |
| 129 | { |
| 130 | for(i=0;i<smlen-64;i++) |
| 131 | m[i] = sm[i + 64]; |
| 132 | *mlen = smlen-64; |
| 133 | } |
| 134 | else |
| 135 | { |
| 136 | for(i=0;i<smlen-64;i++) |
| 137 | m[i] = 0; |
| 138 | } |
| 139 | return ret; |
| 140 | } |