Пример #1
0
/* -- Blinding -------------------------------------------------------------
//
//  Blinding is a measure to protect against side channel attacks. 
//  Blinding randomizes the scalar multiplier.
//
//  Instead of calculating a*P, calculate (a+b mod BPO)*P + B
//
//  Where b = random blinding and B = -b*P
//
// -------------------------------------------------------------------------
*/
void *ed25519_Blinding_Init(
    void *context,                      /* IO: null or ptr blinding context */
    const unsigned char *seed,          /* IN: [size bytes] random blinding seed */
    size_t size)                        /* IN: size of blinding seed */
{
    struct {
        Ext_POINT T;
        U_WORD t[K_WORDS];
        SHA512_CTX H;
        U8 digest[SHA512_DIGEST_LENGTH];
    } d;

    EDP_BLINDING_CTX *ctx = (EDP_BLINDING_CTX*)context;

    if (ctx == 0)
    {
        ctx = (EDP_BLINDING_CTX*)mem_alloc(sizeof(EDP_BLINDING_CTX));
        if (ctx == 0) return 0;
    }

    /* Use edp_custom_blinding to protect generation of the new blinder */

    SHA512_Init(&d.H);
    SHA512_Update(&d.H, edp_custom_blinding.zr, 32);
    SHA512_Update(&d.H, seed, size);
    SHA512_Final(d.digest, &d.H);

    ecp_BytesToWords(ctx->zr, d.digest+32);
    ecp_BytesToWords(d.t, d.digest);
    eco_Mod(d.t);
    ecp_Sub(ctx->bl, _w_BPO, d.t);

    eco_AddReduce(d.t, d.t, edp_custom_blinding.bl);
    edp_BasePointMult(&d.T, d.t, edp_custom_blinding.zr);
    edp_AddPoint(&d.T, &d.T, &edp_custom_blinding.BP);

    edp_ExtPoint2PE(&ctx->BP, &d.T);

    /* clear potentially sensitive data */
    mem_clear (&d, sizeof(d));

    return ctx;
}
Пример #2
0
/*
 * Generate message signature
 */
void ed25519_SignMessage(
    unsigned char *signature,           /* OUT: [64 bytes] signature (R,S) */
    const unsigned char *privKey,       /*  IN: [64 bytes] private key (sk,pk) */
    const void *blinding,               /*  IN: [optional] null or blinding context */
    const unsigned char *msg,           /*  IN: [msg_size bytes] message to sign */
    size_t msg_size)
{
    SHA512_CTX H;
    Affine_POINT R;
    U_WORD a[K_WORDS], t[K_WORDS], r[K_WORDS];
    U8 md[SHA512_DIGEST_LENGTH];

    /* [a:b] = H(sk) */
    SHA512_Init(&H);
    SHA512_Update(&H, privKey, 32);
    SHA512_Final(md, &H);
    ecp_TrimSecretKey(md);              /* a = first 32 bytes */
    ecp_BytesToWords(a, md);

    /* r = H(b + m) mod BPO */
    SHA512_Init(&H);
    SHA512_Update(&H, md+32, 32);
    SHA512_Update(&H, msg, msg_size);
    SHA512_Final(md, &H);
    eco_DigestToWords(r, md);
    eco_Mod(r);                         /* r mod BPO */

    /* R = r*P */
    edp_BasePointMultiply(&R, r, blinding);
    ed25519_PackPoint(signature, R.y, R.x[0]); /* R part of signature */

    /* S = r + H(encoded(R) + pk + m) * a  mod BPO */
    SHA512_Init(&H);
    SHA512_Update(&H, signature, 32);   /* encoded(R) */
    SHA512_Update(&H, privKey+32, 32);  /* pk */
    SHA512_Update(&H, msg, msg_size);   /* m */
    SHA512_Final(md, &H);
    eco_DigestToWords(t, md);

    eco_MulReduce(t, t, a);             /* h()*a */
    eco_AddReduce(t, t, r);
    eco_Mod(t);
    ecp_WordsToBytes(signature+32, t);  /* S part of signature */

    /* Clear sensitive data */
    ecp_SetValue(a, 0);
    ecp_SetValue(r, 0);
}
Пример #3
0
/* Return R = a*P where P is curve25519 base point */
void x25519_BasePointMultiply(OUT U8 *r, IN const U8 *sk)
{
    Ext_POINT S;
    U_WORD t[K_WORDS];

    ecp_BytesToWords(t, sk);
    edp_BasePointMult(&S, t, edp_custom_blinding.zr);

    /* Convert ed25519 point to x25519 point */
    
    /* u = (1 + y)/(1 - y) = (Z + Y)/(Z - Y) */

    ecp_AddReduce(S.t, S.z, S.y);
    ecp_SubReduce(S.z, S.z, S.y);
    ecp_Inverse(S.z, S.z);
    ecp_MulMod(S.t, S.t, S.z);
    ecp_WordsToBytes(r, S.t);
}
Пример #4
0
/* Generate public and private key pair associated with the secret key */
void ed25519_CreateKeyPair(
    unsigned char *pubKey,              /* OUT: public key */
    unsigned char *privKey,             /* OUT: private key */
    const void *blinding,               /* IN: [optional] null or blinding context */
    const unsigned char *sk)            /* IN: secret key (32 bytes) */
{
    U8 md[SHA512_DIGEST_LENGTH];
    U_WORD t[K_WORDS];
    SHA512_CTX H;
    Affine_POINT Q;

    /* [a:b] = H(sk) */
    SHA512_Init(&H);
    SHA512_Update(&H, sk, 32);
    SHA512_Final(md, &H);
    ecp_TrimSecretKey(md);

    ecp_BytesToWords(t, md);
    edp_BasePointMultiply(&Q, t, blinding);
    ed25519_PackPoint(pubKey, Q.y, Q.x[0]);

    memcpy(privKey, sk, 32);
    memcpy(privKey+32, pubKey, 32);
}
Пример #5
0
int curve25519_SelfTest(int level)
{
    int rc = 0;
    U64 A[4], B[4], C[4];
    U8 a[32], b[32], c[32], d[32];

    ecp_AddReduce(A, _w_I, _w_P);
    ECP_MOD(A);
    if (ecp_Cmp(A, _w_I) != 0)
    {
        rc++;
        printf("assert I+p == I mod p FAILED!!\n");
        ecp_PrintHexWords("A_1", A, 4);
    }

    if (ecp_Cmp(_w_I, _w_P) >= 0)
    {
        rc++;
        printf("assert I < P FAILED!!\n");
    }

    if (ecp_Cmp(_w_P, _w_I) <= 0)
    {
        rc++;
        printf("assert P > I FAILED!!\n");
    }

    ecp_MulReduce(B, _w_I, _w_D);
    ECP_MOD(B);
    if (ecp_Cmp(B, _w_IxD) != 0)
    {
        rc++;
        printf("assert I*D FAILED!!\n");
        ecp_PrintHexWords("A_2", B, 4);
    }

    // assert I*I == p-1
    ecp_MulMod(A, _w_I, _w_I);
    if (ecp_Cmp(A, _w_Pm1) != 0)
    {
        rc++;
        printf("assert mul(I,I) == p-1 FAILED!!\n");
        ecp_PrintHexWords("A_3", A, 4);
    }

    // assert I**2 == p-1
    ecp_SqrReduce(B, _w_I);
    ECP_MOD(B);
    if (ecp_Cmp(B, _w_Pm1) != 0)
    {
        rc++;
        printf("assert square(I) == p-1 FAILED!!\n");
        ecp_PrintHexWords("B_4", B, 4);
    }

    // assert (-I)*(-I) == p-1
    ecp_Sub(B, _w_P, _w_I);
    ecp_MulMod(A, B, B);
    if (ecp_Cmp(A, _w_Pm1) != 0)
    {
        rc++;
        printf("assert mul(-I,-I) == p-1 FAILED!!\n");
        ecp_PrintHexWords("A_5", A, 4);
        ecp_PrintHexWords("B_5", B, 4);
    }

    ecp_SetValue(A, 50153);
    ecp_Inverse(B, A);
    ecp_MulMod(A, A, B);
    if (ecp_Cmp(A, _w_One) != 0)
    {
        rc++;
        printf("invmod FAILED!!\n");
        ecp_PrintHexWords("inv_50153", B, 4);
        ecp_PrintHexWords("expected_1", A, 4);
    }

    // assert expmod(d,(p-1)/2,p) == p-1
    ecp_ExpMod(A, _w_D, _b_Pm1d2, 32);
    if (ecp_Cmp(A, _w_Pm1) != 0)
    {
        rc++;
        printf("assert expmod(d,(p-1)/2,p) == p-1 FAILED!!\n");
        ecp_PrintHexWords("A_3", A, 4);
    }

    ecp_CalculateY(a, ecp_BasePoint);
    ecp_BytesToWords(A, a);
    if (ecp_Cmp(A, _w_Gy) != 0)
    {
        rc++;
        printf("assert clacY(Base) == Base.y FAILED!!\n");
        ecp_PrintHexBytes("Calculated_Base.y", a, 32);
    }

    ecp_PointMultiply(a, ecp_BasePoint, _b_Om1, 32);
    if (memcmp(a, ecp_BasePoint, 32) != 0)
    {
        rc++;
        printf("assert (l-1).Base == Base FAILED!!\n");
        ecp_PrintHexBytes("A_5", a, 32);
    }

    ecp_PointMultiply(a, ecp_BasePoint, _b_O, 32);
    ecp_BytesToWords(A, a);
    if (!ecp_IsZero(A))
    {
        rc++;
        printf("assert l.Base == 0 FAILED!!\n");
        ecp_PrintHexBytes("A_6", a, 32);
    }

    // Key generation
    ecp_PointMultiply(a, ecp_BasePoint, pk1, 32);
    ecp_PrintHexBytes("PublicKey1", a, 32);
    ecp_PointMultiply(b, ecp_BasePoint, pk2, 32);
    ecp_PrintHexBytes("PublicKey2", b, 32);

    // ECDH - key exchange
    ecp_PointMultiply(c, b, pk1, 32);
    ecp_PrintHexBytes("SharedKey1", c, 32);
    ecp_PointMultiply(d, a, pk2, 32);
    ecp_PrintHexBytes("SharedKey2", d, 32);
    if (memcmp(c, d, 32) != 0)
    {
        rc++;
        printf("ECDH key exchange FAILED!!\n");
    }

    memset(a, 0x44, 32);        // our secret key
    ecp_PointMultiply(b, ecp_BasePoint, a, 32); // public key
    ecp_PointMultiply(c, b, _b_k1, 32);
    ecp_PointMultiply(d, c, _b_k2, 32);
    if (memcmp(d, b, 32) != 0)
    {
        rc++;
        printf("assert k1.k2.D == D FAILED!!\n");
        ecp_PrintHexBytes("D", d, 4);
        ecp_PrintHexBytes("C", c, 4);
        ecp_PrintHexBytes("A", a, 4);
    }

    ecp_BytesToWords(A, _b_k1);
    ecp_BytesToWords(B, _b_k2);
    eco_InvModBPO(C, A);
    if (ecp_Cmp(C, B) != 0)
    {
        rc++;
        printf("assert 1/k1 == k2 mod BPO FAILED!!\n");
        ecp_PrintHexWords("Calc", C, 4);
        ecp_PrintHexWords("Expt", B, 4);
    }

    eco_MulMod(C, A, B);
    if (ecp_Cmp(C, _w_One) != 0)
    {
        rc++;
        printf("assert k1*k2 == 1 mod BPO FAILED!!\n");
        ecp_PrintHexWords("Calc", C, 4);
    }
    return rc;
}
Пример #6
0
/* K in a little-endian byte array */
void ecp_PointMultiply(
    OUT U8 *PublicKey, 
    IN const U8 *BasePoint, 
    IN const U8 *SecretKey, 
    IN int len)
{
    int i, j, k;
    U_WORD X[K_WORDS];
    XZ_POINT P, Q, *PP[2], *QP[2];

    ecp_BytesToWords(X, BasePoint);

    /* 1: P = (2k+1)G, Q = (2k+2)G */
    /* 0: Q = (2k+1)G, P = (2k)G */

    /* Find first non-zero bit */
    while (len-- > 0)
    {
        k = SecretKey[len];
        for (i = 0; i < 8; i++, k <<= 1)
        {
            /* P = kG, Q = (k+1)G */
            if (k & 0x80)
            {
                /* We have first non-zero bit 
                // This is always bit 254 for keys created according to the spec.
                // Start with randomized base point 
                */

                ecp_Add(P.Z, X, edp_custom_blinding.zr);    /* P.Z = random */
                ecp_MulReduce(P.X, X, P.Z);
                ecp_MontDouble(&Q, &P);

                PP[1] = &P; PP[0] = &Q;
                QP[1] = &Q; QP[0] = &P;

                /* Everything we reference in the below loop are on the stack
                // and already touched (cached) 
                */

                while (++i < 8) { k <<= 1; ECP_MONT(7); }
                while (len > 0)
                {
                    k = SecretKey[--len];
                    ECP_MONT(7);
                    ECP_MONT(6);
                    ECP_MONT(5);
                    ECP_MONT(4);
                    ECP_MONT(3);
                    ECP_MONT(2);
                    ECP_MONT(1);
                    ECP_MONT(0);
                }

                ecp_Inverse(Q.Z, P.Z);
                ecp_MulMod(X, P.X, Q.Z);
                ecp_WordsToBytes(PublicKey, X);
                return;
            }
        }
    }
    /* K is 0 */
    mem_fill(PublicKey, 0, 32);
}