decaf_crypto.c 3.54 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
/**
 * @cond internal
 * @file decaf_crypto.c
 * @copyright
 *   Copyright (c) 2015 Cryptography Research, Inc.  \n
 *   Released under the MIT License.  See LICENSE.txt for license information.
 * @author Mike Hamburg
 * @brief Decaf cyrpto routines. 
 */

#include "decaf_crypto.h"
#include <string.h>

void decaf_448_derive_private_key (
    decaf_448_private_key_t priv,
    const decaf_448_symmetric_key_t proto
) {
    const char *magic = "decaf_448_derive_private_key";
    keccak_sponge_t sponge;
    uint8_t encoded_scalar[64];
    decaf_448_point_t pub;
    shake256_init(sponge);
    shake256_update(sponge, proto, sizeof(decaf_448_symmetric_key_t));
    shake256_update(sponge, (const unsigned char *)magic, strlen(magic));
    shake256_final(sponge, encoded_scalar, sizeof(encoded_scalar));
    shake256_destroy(sponge);
    
    memcpy(priv->sym, proto, sizeof(decaf_448_symmetric_key_t));
    decaf_448_scalar_decode_long(priv->secret_scalar, encoded_scalar, sizeof(encoded_scalar));
    
    decaf_448_precomputed_scalarmul(pub, decaf_448_precomputed_base, priv->secret_scalar);
    decaf_448_point_encode(priv->pub, pub);
    
    decaf_bzero(encoded_scalar, sizeof(encoded_scalar));
}

void
decaf_448_destroy_private_key (
    decaf_448_private_key_t priv
)  {
    decaf_bzero((void*)priv, sizeof(decaf_448_private_key_t));
}

void decaf_448_private_to_public (
    decaf_448_public_key_t pub,
    const decaf_448_private_key_t priv
) {
    memcpy(pub, priv->pub, sizeof(decaf_448_public_key_t));
}

decaf_bool_t
decaf_448_shared_secret (
    uint8_t *shared,
    size_t shared_bytes,
    const decaf_448_private_key_t my_privkey,
    const decaf_448_public_key_t your_pubkey
) {
    decaf_448_point_t point;
    uint8_t ss_ser[DECAF_448_SER_BYTES];
    const char *nope = "decaf_448_ss_invalid";
    decaf_bool_t ret = decaf_448_point_decode(point, your_pubkey, DECAF_FALSE);
    decaf_448_point_scalarmul(point, point, my_privkey->secret_scalar);
    
    unsigned i;
    /* Lexsort keys.  Less will be -1 if mine is less, and 0 otherwise. */
    uint16_t less = 0;
    for (i=0; i<DECAF_448_SER_BYTES; i++) {
        uint16_t delta = my_privkey->pub[i];
        delta -= your_pubkey[i];
        /* Case:
         * = -> delta = 0 -> hi delta-1 = -1, hi delta = 0
         * > -> delta > 0 -> hi delta-1 = 0, hi delta = 0
         * < -> delta < 0 -> hi delta-1 = (doesnt matter), hi delta = -1
         */
        less &= delta-1;
        less |= delta;
    }
    less >>= 8;

    keccak_sponge_t sponge;
    shake256_init(sponge);

    /* update the lesser */
    for (i=0; i<sizeof(ss_ser); i++) {
        ss_ser[i] = (my_privkey->pub[i] & less) | (your_pubkey[i] & ~less);
    }
    shake256_update(sponge, ss_ser, sizeof(ss_ser));

    /* update the greater */
    for (i=0; i<sizeof(ss_ser); i++) {
        ss_ser[i] = (my_privkey->pub[i] & ~less) | (your_pubkey[i] & less);
    }
    shake256_update(sponge, ss_ser, sizeof(ss_ser));
    
    /* encode the shared secret but mask with secret key */
    decaf_448_point_encode(ss_ser, point);
    
    /* If invalid, then replace ... */
    for (i=0; i<sizeof(ss_ser); i++) {
        ss_ser[i] &= ret;
        
        if (i < sizeof(my_privkey->sym)) {
            ss_ser[i] |= my_privkey->sym[i] & ~ret;
        } else if (i - sizeof(my_privkey->sym) < strlen(nope)) {
            ss_ser[i] |= nope[i-sizeof(my_privkey->sym)] & ~ret;
        }
    }

    shake256_update(sponge, ss_ser, sizeof(ss_ser));
    shake256_final(sponge, shared, shared_bytes);
    shake256_destroy(sponge);
    
    decaf_bzero(ss_ser, sizeof(ss_ser));
    
    return ret;
}