/* Compute an DH shared secret between private_key and public_key. Return
   the result in computed_key and the
   length of the result in bytes in *computed_key_len.  Return 0 iff
   successful. */
int ccdh_compute_key(ccdh_full_ctx_t private_key, ccdh_pub_ctx_t public_key,
                     cc_unit *r) {
    int result = CCDH_ERROR_DEFAULT;
    ccdh_const_gp_t gp = ccdh_ctx_gp(private_key);
    cc_size n=ccdh_gp_n(gp);

    /* Validated the public key */
    result = ccdh_check_pub(gp,public_key);
    if(result!=0)
    {
        goto errOut;
    }

    /* Actual compuation */
    cczp_power(gp.zp, r, ccdh_ctx_y(public_key), ccdh_ctx_x(private_key));

    /* Result can't be 0 (computation issue) or 1 (y in the group) */
    result = CCDH_INVALID_INPUT;
    if (!(ccn_is_zero_or_one(n,r)))
    {
        result = 0;
    }

errOut:
    return result;
}
Exemple #2
0
OSStatus SecDHGenerateKeypair(SecDHContext dh, uint8_t *pub_key,
	size_t *pub_key_len)
{
    int result;
    ccdh_gp_t gp = SecDH_gp(dh);
    ccdh_full_ctx_t priv = SecDH_priv(dh);

    if((result = ccdh_generate_key(gp, &dhrng, priv)))
        return result;

    /* output y as a big endian byte buffer */
    size_t ylen = ccn_write_uint_size(ccdh_gp_n(gp), ccdh_ctx_y(priv));
    if(*pub_key_len < ylen)
       return errSecBufferTooSmall;
    ccn_write_uint(ccdh_gp_n(gp),ccdh_ctx_y(priv), ylen, pub_key);
    *pub_key_len = ylen;

    return errSecSuccess;
}
int ccdh_generate_key(ccdh_const_gp_t gp,  struct ccrng_state *rng, ccdh_full_ctx_t key)
{
    int result=CCDH_ERROR_DEFAULT;
    ccdh_ctx_init(gp, key);
    const cc_unit *g = ccdh_gp_g(gp);
    cc_unit *x = ccdh_ctx_x(key);
    cc_unit *y = ccdh_ctx_y(key);

    /* Generate the private key: x per PKCS #3 */
    cc_require((result=ccdh_generate_private_key(gp,x,rng))==0,errOut);

    /* Generate the public key: y=g^x mod p */
    cczp_power(gp.zp, y, g, x);
    result = 0;

errOut:
    return result;
}
int ccdh_import_priv(ccdh_const_gp_t gp, size_t in_len, const uint8_t *in,
                     ccdh_full_ctx_t key)
{
    const cc_unit *g = ccdh_gp_g(gp);
    ccdh_ctx_init(gp, key);
    cc_unit *x = ccdh_ctx_x(key);
    cc_unit *y = ccdh_ctx_y(key);

    if ((ccn_read_uint(ccdh_gp_n(gp), x, in_len, in)))
        return CCDH_INVALID_INPUT;
    
    if (ccn_cmp(ccdh_gp_n(gp), x, cczp_prime(gp.zp)) >= 0)
        return CCDH_SAFETY_CHECK;
    
    /* Generate the public key: y=g^x mod p */
    cczp_power(gp.zp, y, g, x);
    
    return 0;
}
Exemple #5
0
int ccdh_test_compute_vector(const struct ccdh_compute_vector *v)
{
    int result,r1,r2;
    const cc_size n = ccn_nof(v->len);
    const size_t s = ccn_sizeof_n(n);
    unsigned char z[v->zLen];
    size_t zLen;
    unsigned char tmp[v->zLen]; // for negative testing
    uint32_t status=0;
    uint32_t nb_test=0;

    ccdh_gp_decl(s, gp);
    ccdh_full_ctx_decl(s, a);
    ccdh_full_ctx_decl(s, b);
    cc_unit p[n];
    cc_unit g[n];
    cc_unit r[n];
    cc_unit q[n];

    // Bail to errOut when unexpected error happens.
    // Try all usecases otherwise

    if((result=ccn_read_uint(n, p, v->pLen, v->p)))
        goto errOut;
    if((result=ccn_read_uint(n, g, v->gLen, v->g)))
        goto errOut;
    if((result=ccn_read_uint(n, q, v->qLen, v->q)))
        goto errOut;

    ccdh_init_gp_with_order(gp, n, p, g, q);

    ccdh_ctx_init(gp, a);
    ccdh_ctx_init(gp, b);

    if((result=ccn_read_uint(n, ccdh_ctx_x(a), v->xaLen, v->xa))) // private key
        goto errOut;
    if((result=ccn_read_uint(n, ccdh_ctx_y(a), v->yaLen, v->ya))) // public key
        goto errOut;
    if((result=ccn_read_uint(n, ccdh_ctx_x(b), v->xbLen, v->xb))) // private key
        goto errOut;
    if((result=ccn_read_uint(n, ccdh_ctx_y(b), v->ybLen, v->yb))) // public key
        goto errOut;

    /*
     * Main test
     */

    /* try one side */
    zLen = v->zLen;
    r1=ccdh_compute_key(a, b, r);
    ccn_write_uint_padded(n, r, zLen, z);
    r1|=memcmp(z, v->z, zLen);

    /* try the other side */
    zLen = v->zLen;
    r2=ccdh_compute_key(b, a, r);
    ccn_write_uint_padded(n, r, zLen, z);
    r2|=memcmp(z, v->z, zLen);

    if ((!(r1||r2) && v->valid)||((r1||r2) && !v->valid))
    {
        status|=1<<nb_test;
    }
    nb_test++;

    // We are done if the test is not valid
    if (!v->valid) goto doneOut;

    /*
     * Corner case / negative testing
     * Only applicable for valid tests
     */

    /* Output is 1 (use private key is (p-1)/2)*/
    if((result=ccn_read_uint(n, ccdh_ctx_x(a), v->pLen, v->p))) // private key
        goto errOut;
    ccn_sub1(n,ccdh_ctx_x(a),ccdh_ctx_x(a),1);
    ccn_shift_right(n,ccdh_ctx_x(a),ccdh_ctx_x(a),1);
    if ((result=ccdh_compute_key(a, b, r))!=0)
    {
        status|=1<<nb_test;
    }
    if((result=ccn_read_uint(n, ccdh_ctx_x(a), v->xaLen, v->xa))) // restore private key
        goto errOut;
    nb_test++;
    
    
    /* negative testing (1 < y < p-1)*/
    /* public y = 0 */
    zLen = v->zLen;
    cc_zero(sizeof(tmp),tmp);
    if((result=ccn_read_uint(n, ccdh_ctx_y(b), zLen, tmp)))
    {
        goto errOut;
    }
    if((result=ccdh_compute_key(a, b, r))!=0)
    {
        status|=1<<nb_test;
    }
    nb_test++;

    /* public y = 1 */
    zLen = v->zLen;
    cc_zero(sizeof(tmp),tmp);
    tmp[zLen-1]=1;
    if((result=ccn_read_uint(n, ccdh_ctx_y(b), zLen, tmp)))
    {
        goto errOut;
    }
    if((result=ccdh_compute_key(a, b, r))!=0)
    {
        status|=1<<nb_test;
    }
    nb_test++;

    /* public y = p */
    if((result=ccn_read_uint(n, ccdh_ctx_y(b), v->pLen, v->p)))
        goto errOut;

    if((result=ccdh_compute_key(a, b, r))!=0)
    {
        status|=1<<nb_test;
    }
    nb_test++;

    /* public y = p-1 */
    if((result=ccn_read_uint(n, ccdh_ctx_y(b), v->pLen, v->p)))
    {
        goto errOut;
    }
    ccn_sub1(n,ccdh_ctx_y(b),ccdh_ctx_y(b),1);

    if((result=ccdh_compute_key(a, b, r))!=0)
    {
        status|=1<<nb_test;
    }
    nb_test++;

    /* 
     * When the order is in defined in the group 
     *  check that the implementation check the order of the public value:
     *      public y = g+1 (for rfc5114 groups, g+1 is not of order q)
     */
    if (ccdh_gp_order_bitlen(gp))
    {
        if((result=ccn_read_uint(n, ccdh_ctx_y(b), v->gLen, v->g)))
        {
            goto errOut;
        }
        ccn_add1(n,ccdh_ctx_y(b),ccdh_ctx_y(b),1);

        if((result=ccdh_compute_key(a, b, r))!=0)
        {
            status|=1<<nb_test;
        }
        nb_test++;
    }


    /* positive testing at the boundaries of (1 < y < p-1)*/

    // Don't set the order in gp because 2 and p-2 are not of order q
    ccdh_init_gp(gp, n, p, g, 0);

    /* public y = 2 */
    zLen = v->zLen;
    cc_zero(sizeof(tmp),tmp);
    tmp[zLen-1]=2;
    if((result=ccn_read_uint(n, ccdh_ctx_y(b), zLen, tmp)))
    {
        goto errOut;
    }
    if((result=ccdh_compute_key(a, b, r))==0)
    {
        status|=1<<nb_test;
    }
    nb_test++;

    /* public y = p-2 */
    if((result=ccn_read_uint(n, ccdh_ctx_y(b), v->pLen, v->p)))
    {
        goto errOut;
    }
    ccn_sub1(n,ccdh_ctx_y(b),ccdh_ctx_y(b),2);

    if((result=ccdh_compute_key(a, b, r))==0)
    {
        status|=1<<nb_test;
    }
    nb_test++;

    /* Negative testing: p is even */
    if((result=ccn_read_uint(n, p, v->pLen, v->p)))
        goto errOut;
    ccn_set_bit(p,0,0); // Set LS bit to 0
    ccdh_init_gp(gp, n, p, g, 0);
    ccdh_ctx_init(gp, a);
    ccdh_ctx_init(gp, b);

    if((result=ccdh_compute_key(a, b, r))!=0)
    {
        status|=1<<nb_test;
    }
    nb_test++;


    /* Test aftermath */
doneOut:
    if ((nb_test==0) || (status!=((1<<nb_test)-1)))
    {
        result=1;
    }
    else
    {
        result=0; // Test is successful, Yeah!
    }

errOut:
    return result;
}