/* Copyright (c) 2016, Google Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include <openssl/curve25519.h> #include <assert.h> #include <string.h> #include <openssl/bytestring.h> #include <openssl/mem.h> #include <openssl/rand.h> #include <openssl/sha.h> #include "../fipsmodule/bn/internal.h" #include "../internal.h" #include "./internal.h" // The following precomputation tables are for the following // points used in the SPAKE2 protocol. // // N: // x: 49918732221787544735331783592030787422991506689877079631459872391322455579424 // y: 54629554431565467720832445949441049581317094546788069926228343916274969994000 // encoded: 10e3df0ae37d8e7a99b5fe74b44672103dbddcbd06af680d71329a11693bc778 // // M: // x: 31406539342727633121250288103050113562375374900226415211311216773867585644232 // y: 21177308356423958466833845032658859666296341766942662650232962324899758529114 // encoded: 5ada7e4bf6ddd9adb6626d32131c6b5c51a1e347a3478f53cfcf441b88eed12e // // These points and their precomputation tables are generated with the // following Python code. For a description of the precomputation table, // see curve25519.c in this directory. // // Exact copies of the source code are kept in bug 27296743. /* import hashlib import ed25519 as E # http://ed25519.cr.yp.to/python/ed25519.py SEED_N = 'edwards25519 point generation seed (N)' SEED_M = 'edwards25519 point generation seed (M)' def genpoint(seed): v = hashlib.sha256(seed).digest() it = 1 while True: try: x,y = E.decodepoint(v) except Exception, e: print e it += 1 v = hashlib.sha256(v).digest() continue print "Found in %d iterations:" % it print " x = %d" % x print " y = %d" % y print " Encoded (hex)" print E.encodepoint((x,y)).encode('hex') return (x,y) def gentable(P): t = [] for i in range(1,16): k = ((i >> 3 & 1) * (1 << 192) + (i >> 2 & 1) * (1 << 128) + (i >> 1 & 1) * (1 << 64) + (i & 1)) t.append(E.scalarmult(P, k)) return ''.join(E.encodeint(x) + E.encodeint(y) for (x,y) in t) def printtable(table, name): print "static const uint8_t %s[15 * 2 * 32] = {" % name, for i in range(15 * 2 * 32): if i % 12 == 0: print "\n ", print " 0x%02x," % ord(table[i]), print "\n};" if __name__ == "__main__": print "Searching for N" N = genpoint(SEED_N) print "Generating precomputation table for N" Ntable = gentable(N) printtable(Ntable, "kSpakeNSmallPrecomp") print "Searching for M" M = genpoint(SEED_M) print "Generating precomputation table for M" Mtable = gentable(M) printtable(Mtable, "kSpakeMSmallPrecomp") */ static const uint8_t kSpakeNSmallPrecomp[15 * 2 * 32] = …; static const uint8_t kSpakeMSmallPrecomp[15 * 2 * 32] = …; SPAKE2_CTX *SPAKE2_CTX_new(enum spake2_role_t my_role, const uint8_t *my_name, size_t my_name_len, const uint8_t *their_name, size_t their_name_len) { … } void SPAKE2_CTX_free(SPAKE2_CTX *ctx) { … } // left_shift_3 sets |n| to |n|*8, where |n| is represented in little-endian // order. static void left_shift_3(uint8_t n[32]) { … } scalar; // kOrder is the order of the prime-order subgroup of curve25519. static const scalar kOrder = …; // scalar_cmov copies |src| to |dest| if |mask| is all ones. static void scalar_cmov(scalar *dest, const scalar *src, crypto_word_t mask) { … } // scalar_double sets |s| to |2×s|. static void scalar_double(scalar *s) { … } // scalar_add sets |dest| to |dest| plus |src|. static void scalar_add(scalar *dest, const scalar *src) { … } int SPAKE2_generate_msg(SPAKE2_CTX *ctx, uint8_t *out, size_t *out_len, size_t max_out_len, const uint8_t *password, size_t password_len) { … } static void update_with_length_prefix(SHA512_CTX *sha, const uint8_t *data, const size_t len) { … } int SPAKE2_process_msg(SPAKE2_CTX *ctx, uint8_t *out_key, size_t *out_key_len, size_t max_out_key_len, const uint8_t *their_msg, size_t their_msg_len) { … }