1/* $OpenBSD: ed25519.c,v 1.3 2013/12/09 11:03:45 markus Exp $ */ 2 3/* 4 * Public Domain, Authors: Daniel J. Bernstein, Niels Duif, Tanja Lange, 5 * Peter Schwabe, Bo-Yin Yang. 6 * Copied from supercop-20130419/crypto_sign/ed25519/ref/ed25519.c 7 * 8 * Modified to use lws genhash by Andy Green <andy@warmcat.com> 9 */ 10 11#include <libwebsockets.h> 12#include <lws-ssh.h> 13#include "ge25519.h" 14 15int 16crypto_hash_sha512(uint8_t *hash64, const uint8_t *data, size_t len) 17{ 18 struct lws_genhash_ctx ctx; 19 int ret; 20 21 if (lws_genhash_init(&ctx, LWS_GENHASH_TYPE_SHA512)) { 22 lwsl_notice("Failed to init SHA512\n"); 23 return 0; 24 } 25 26 ret = lws_genhash_update(&ctx, data, len); 27 28 if (lws_genhash_destroy(&ctx, hash64)) 29 lwsl_notice("genhash destroy failed\n"); 30 31 return ret ? 0 : 64; 32} 33 34 35static void 36get_hram(unsigned char *hram, const unsigned char *sm, 37 const unsigned char *pk, unsigned char *playground, 38 size_t smlen) 39{ 40 unsigned long long i; 41 42 for (i = 0; i < 32; ++i) 43 playground[i] = sm[i]; 44 for (i = 32; i < 64; ++i) 45 playground[i] = pk[i-32]; 46 for (i = 64; i < smlen; ++i) 47 playground[i] = sm[i]; 48 49 crypto_hash_sha512(hram, playground, smlen); 50} 51 52 53int crypto_sign_ed25519_keypair( 54 struct lws_context *context, 55 unsigned char *pk, 56 unsigned char *sk 57 ) 58{ 59 sc25519 scsk; 60 ge25519 gepk; 61 unsigned char extsk[64]; 62 int i; 63 64 lws_get_random(context, sk, 32); 65 crypto_hash_sha512(extsk, sk, 32); 66 extsk[0] &= 248; 67 extsk[31] &= 127; 68 extsk[31] |= 64; 69 70 sc25519_from32bytes(&scsk,extsk); 71 72 ge25519_scalarmult_base(&gepk, &scsk); 73 ge25519_pack(pk, &gepk); 74 for(i=0;i<32;i++) 75 sk[32 + i] = pk[i]; 76 return 0; 77} 78 79int crypto_sign_ed25519( 80 unsigned char *sm, 81 unsigned long long *smlen, 82 const unsigned char *m, size_t mlen, 83 const unsigned char *sk 84 ) 85{ 86 sc25519 sck, scs, scsk; 87 ge25519 ger; 88 unsigned char r[32]; 89 unsigned char s[32]; 90 unsigned char extsk[64]; 91 unsigned long long i; 92 unsigned char hmg[crypto_hash_sha512_BYTES]; 93 unsigned char hram[crypto_hash_sha512_BYTES]; 94 95 crypto_hash_sha512(extsk, sk, 32); 96 extsk[0] &= 248; 97 extsk[31] &= 127; 98 extsk[31] |= 64; 99 100 *smlen = mlen+64; 101 for(i=0;i<mlen;i++) 102 sm[64 + i] = m[i]; 103 for(i=0;i<32;i++) 104 sm[32 + i] = extsk[32+i]; 105 106 crypto_hash_sha512(hmg, sm+32, mlen+32); 107 /* Generate k as h(extsk[32],...,extsk[63],m) */ 108 109 /* Computation of R */ 110 sc25519_from64bytes(&sck, hmg); 111 ge25519_scalarmult_base(&ger, &sck); 112 ge25519_pack(r, &ger); 113 114 /* Computation of s */ 115 for (i = 0; i < 32; i++) 116 sm[i] = r[i]; 117 118 get_hram(hram, sm, sk + 32, sm, (size_t)mlen + 64); 119 120 sc25519_from64bytes(&scs, hram); 121 sc25519_from32bytes(&scsk, extsk); 122 sc25519_mul(&scs, &scs, &scsk); 123 124 sc25519_add(&scs, &scs, &sck); 125 126 sc25519_to32bytes(s,&scs); /* cat s */ 127 for (i = 0; i < 32; i++) 128 sm[32 + i] = s[i]; 129 130 return 0; 131} 132 133int crypto_verify_32(const unsigned char *x,const unsigned char *y) 134{ 135 unsigned int differentbits = 0; 136#define F(i) differentbits |= x[i] ^ y[i]; 137 F(0) 138 F(1) 139 F(2) 140 F(3) 141 F(4) 142 F(5) 143 F(6) 144 F(7) 145 F(8) 146 F(9) 147 F(10) 148 F(11) 149 F(12) 150 F(13) 151 F(14) 152 F(15) 153 F(16) 154 F(17) 155 F(18) 156 F(19) 157 F(20) 158 F(21) 159 F(22) 160 F(23) 161 F(24) 162 F(25) 163 F(26) 164 F(27) 165 F(28) 166 F(29) 167 F(30) 168 F(31) 169 return (int)((1 & ((differentbits - 1) >> 8)) - 1); 170} 171 172int crypto_sign_ed25519_open( 173 unsigned char *m,unsigned long long *mlen, 174 const unsigned char *sm,unsigned long long smlen, 175 const unsigned char *pk 176 ) 177{ 178 unsigned int i; 179 int ret; 180 unsigned char t2[32]; 181 ge25519 get1, get2; 182 sc25519 schram, scs; 183 unsigned char hram[crypto_hash_sha512_BYTES]; 184 185 *mlen = (unsigned long long) -1; 186 if (smlen < 64) { 187 lwsl_notice("a\n"); 188 189 return -1; 190 } 191 192 if (ge25519_unpackneg_vartime(&get1, pk)) { 193 lwsl_notice("b\n"); 194 return -1; 195 } 196 197 get_hram(hram,sm,pk,m, (size_t)smlen); 198 199 sc25519_from64bytes(&schram, hram); 200 201 sc25519_from32bytes(&scs, sm+32); 202 203 ge25519_double_scalarmult_vartime(&get2, &get1, &schram, &ge25519_base, &scs); 204 ge25519_pack(t2, &get2); 205 206 ret = crypto_verify_32(sm, t2); 207 lwsl_notice("vf says %d\n", ret); 208 209 if (!ret) 210 { 211 for(i=0;i<smlen-64;i++) 212 m[i] = sm[i + 64]; 213 *mlen = smlen-64; 214 } 215 else 216 { 217 for(i=0;i<smlen-64;i++) 218 m[i] = 0; 219 } 220 return ret; 221} 222