예제 #1
0
파일: ntru.c 프로젝트: tbuktu/libntru
void ntru_decrypt_poly(NtruIntPoly *e, NtruEncPrivKey *priv, uint16_t q, NtruIntPoly *d) {
    ntru_mult_priv(&priv->t, e, d, q-1);
    ntru_mult_fac(d, 3);
    ntru_add(d, e);
    ntru_mod_center(d, q);
    ntru_mod3(d);
}
예제 #2
0
파일: ntru.c 프로젝트: tbuktu/libntru
uint8_t ntru_gen_key_pair_single(const NtruEncParams *params, NtruEncPrivKey *priv, NtruEncPubKey *pub, NtruIntPoly *fq, NtruRandContext *rand_ctx) {
    uint16_t N = params->N;
    uint16_t q = params->q;
    uint16_t df1 = params->df1;
#ifndef NTRU_AVOID_HAMMING_WT_PATENT
    uint16_t df2 = params->df2;
    uint16_t df3 = params->df3;
#endif   /* NTRU_AVOID_HAMMING_WT_PATENT */

    if (q & (q-1))   /* check that modulus is a power of 2 */
        return NTRU_ERR_INVALID_PARAM;

    /* choose a random f that is invertible mod q */
#ifndef NTRU_AVOID_HAMMING_WT_PATENT
    if (params->prod_flag) {
        NtruPrivPoly *t = &priv->t;
        t->prod_flag = 1;
        t->poly.prod.N = N;
        priv->q = q;
        for (;;) {
            /* choose random t, find the inverse of 3t+1 */
            if (!ntru_rand_prod(N, df1, df2, df3, df3, &t->poly.prod, rand_ctx))
                return NTRU_ERR_PRNG;
            if (ntru_invert(t, q-1, fq))
                break;
        }
    }
    else
#endif   /* NTRU_AVOID_HAMMING_WT_PATENT */
    {
        NtruPrivPoly *t = &priv->t;
        t->prod_flag = 0;
        priv->q = q;
        for (;;) {
            /* choose random t, find the inverse of 3t+1 */
            if (!ntru_rand_tern(N, df1, df1, &t->poly.tern, rand_ctx))
                return NTRU_ERR_PRNG;
            if (ntru_invert(t, q-1, fq))
                break;
        }
    }

    /* choose a random g */
    NtruPrivPoly g;
    uint8_t result = ntru_gen_g(params, &g, rand_ctx);
    if (result != NTRU_SUCCESS)
        return result;

    NtruIntPoly *h = &pub->h;
    if (!ntru_mult_priv(&g, fq, h, q-1))
        return NTRU_ERR_INVALID_PARAM;
    ntru_mult_fac(h, 3);
    ntru_mod_mask(h, q-1);

    ntru_clear_priv(&g);

    pub->q = q;

    return NTRU_SUCCESS;
}
예제 #3
0
파일: ntru.c 프로젝트: jl777/libntru
uint8_t ntru_encrypt(uint8_t *msg, uint16_t msg_len, NtruEncPubKey *pub, const NtruEncParams *params, NtruRandContext *rand_ctx, uint8_t *enc) {
    uint16_t N = params->N;
    uint16_t q = params->q;
    uint16_t db = params->db;
    uint16_t max_len_bytes = ntru_max_msg_len(params);
    uint16_t dm0 = params->dm0;

    if (max_len_bytes > 255)
        return NTRU_ERR_INVALID_MAX_LEN;
    if (msg_len > max_len_bytes)
        return NTRU_ERR_MSG_TOO_LONG;

    for (;;) {
        /* M = b|octL|msg|p0 */
        uint8_t b[db/8];
        if (ntru_rand_generate(b, db/8, rand_ctx) != NTRU_SUCCESS)
            return NTRU_ERR_PRNG;

        uint16_t M_len = db/8 + 1 + max_len_bytes + 1;
        uint8_t M[M_len];
        memcpy(&M, &b, db/8);
        uint8_t *M_head = (uint8_t*)&M + db/8;
        *M_head = msg_len;
        M_head++;
        memcpy(M_head, msg, msg_len);
        M_head += msg_len;
        memset(M_head, 0, max_len_bytes+1-msg_len);

        NtruIntPoly mtrin;
        ntru_from_sves((uint8_t*)&M, M_len, N, &mtrin);

        uint16_t blen = params->db / 8;
        uint16_t sdata_len = sizeof(params->oid) + msg_len + blen + blen;
        uint8_t sdata[sdata_len];
        ntru_get_seed(msg, msg_len, &pub->h, (uint8_t*)&b, params, (uint8_t*)&sdata);

        NtruIntPoly R;
        NtruPrivPoly r;
        ntru_gen_blind_poly((uint8_t*)&sdata, sdata_len, params, &r);
        ntru_mult_priv(&r, &pub->h, &R, q);
        uint16_t oR4_len = (N*2+7) / 8;
        uint8_t oR4[oR4_len];
        ntru_to_arr4(&R, (uint8_t*)&oR4);
        NtruIntPoly mask;
        ntru_MGF((uint8_t*)&oR4, oR4_len, params, &mask);
        ntru_add_int(&mtrin, &mask);

        ntru_mod3(&mtrin);

        if (!ntru_check_rep_weight(&mtrin, dm0))
            continue;

        ntru_add_int(&R, &mtrin);
        ntru_to_arr(&R, q, enc);
        return NTRU_SUCCESS;
    }
}
예제 #4
0
파일: ntru.c 프로젝트: tbuktu/libntru
uint8_t ntru_gen_pub(const NtruEncParams *params, NtruEncPrivKey *priv, NtruEncPubKey *pub, NtruRandContext *rand_ctx) {
    ntru_set_optimized_impl();

    uint16_t q = params->q;
    NtruIntPoly fq;
    if (!ntru_invert(&priv->t, q-1, &fq))
        return NTRU_ERR_INVALID_KEY;
    NtruIntPoly *h = &pub->h;
    NtruPrivPoly g;
    uint8_t result = ntru_gen_g(params, &g, rand_ctx);
    if (result != NTRU_SUCCESS)
        return result;
    if (!ntru_mult_priv(&g, &fq, h, q-1))
        return NTRU_ERR_INVALID_PARAM;
    ntru_clear_int(&fq);
    ntru_mult_fac(h, 3);
    ntru_mod_mask(h, q-1);
    pub->q = q;
    return NTRU_SUCCESS;
}
예제 #5
0
파일: ntru.c 프로젝트: tbuktu/libntru
uint8_t ntru_gen_key_pair_multi(const NtruEncParams *params, NtruEncPrivKey *priv, NtruEncPubKey *pub, NtruRandContext *rand_ctx, uint32_t num_pub) {
    ntru_set_optimized_impl();

    uint16_t q = params->q;
    NtruIntPoly fq;
    uint8_t result = ntru_gen_key_pair_single(params, priv, pub, &fq, rand_ctx);
    if (result != NTRU_SUCCESS)
        return result;
    uint32_t i;
    for (i=1; i<num_pub; i++) {
        NtruIntPoly *h = &pub[i].h;
        NtruPrivPoly g;
        result = ntru_gen_g(params, &g, rand_ctx);
        if (result != NTRU_SUCCESS)
            return result;
        if (!ntru_mult_priv(&g, &fq, h, q-1))
            return NTRU_ERR_INVALID_PARAM;
        ntru_mult_fac(h, 3);
        ntru_mod_mask(h, q-1);
        pub[i].q = q;
    }
    ntru_clear_int(&fq);
    return result;
}
예제 #6
0
파일: ntru.c 프로젝트: tbuktu/libntru
uint8_t ntru_decrypt(uint8_t *enc, NtruEncKeyPair *kp, const NtruEncParams *params, uint8_t *dec, uint16_t *dec_len) {
    ntru_set_optimized_impl();

    uint16_t N = params->N;
    uint16_t q = params->q;
    uint16_t db = params->db;
    uint16_t max_len_bytes = ntru_max_msg_len(params);
    uint16_t dm0 = params->dm0;

    if (q & (q-1))   /* check that modulus is a power of 2 */
        return NTRU_ERR_INVALID_PARAM;
    if (max_len_bytes > 255)
        return NTRU_ERR_INVALID_MAX_LEN;

    uint16_t blen = db / 8;
    uint8_t retcode = NTRU_SUCCESS;

    NtruIntPoly e;
    ntru_from_arr(enc, N, q, &e);
    NtruIntPoly ci;
    ntru_decrypt_poly(&e, &kp->priv, q, &ci);

    if (!ntru_check_rep_weight(&ci, dm0) && retcode==NTRU_SUCCESS)
        retcode = NTRU_ERR_DM0_VIOLATION;

    NtruIntPoly cR = e;
    ntru_sub(&cR, &ci);
    ntru_mod_mask(&cR, q-1);

    uint16_t coR4_len = (N*2+7) / 8;
    uint8_t coR4[coR4_len];
    ntru_to_arr4(&cR, (uint8_t*)&coR4);

    NtruIntPoly mask;
    ntru_MGF((uint8_t*)&coR4, coR4_len, params, &mask);
    NtruIntPoly cmtrin = ci;
    ntru_sub(&cmtrin, &mask);
    ntru_mod3(&cmtrin);
    uint16_t cM_len_bits = (N*3+1) / 2;
    uint16_t cM_len_bytes = (cM_len_bits+7) / 8;
    uint8_t cM[cM_len_bytes+3];   /* 3 extra bytes for ntru_to_sves() */
    if (!ntru_to_sves(&cmtrin, (uint8_t*)&cM) && retcode==NTRU_SUCCESS)
        retcode = NTRU_ERR_INVALID_ENCODING;

    uint8_t cb[blen];
    uint8_t *cM_head = cM;
    memcpy(cb, cM_head, blen);
    cM_head += blen;
    uint8_t cl = *cM_head;   /* llen=1, so read one byte */
    cM_head++;
    if (cl > max_len_bytes) {
        if (retcode == NTRU_SUCCESS)
            retcode = NTRU_ERR_MSG_TOO_LONG;
        cl = max_len_bytes;   /* prevent buffer overrun in memcpy below */
    }

    memcpy(dec, cM_head, cl);
    cM_head += cl;

    uint8_t *i;
    for (i=cM_head; i<cM+cM_len_bytes; i++)
        if (*i && retcode==NTRU_SUCCESS)
            retcode = NTRU_ERR_NO_ZERO_PAD;

    uint16_t sdata_len = sizeof(params->oid) + cl + blen + db/8;
    uint8_t sdata[sdata_len];
    ntru_get_seed(dec, cl, &kp->pub.h, (uint8_t*)&cb, params, (uint8_t*)&sdata);

    NtruPrivPoly cr;
    ntru_gen_blind_poly((uint8_t*)&sdata, sdata_len, params, &cr);
    NtruIntPoly cR_prime;
    ntru_mult_priv(&cr, &kp->pub.h, &cR_prime, q-1);
    if (!ntru_equals_int(&cR_prime, &cR) && retcode==NTRU_SUCCESS)
        retcode = NTRU_ERR_INVALID_ENCODING;

    *dec_len = cl;
    return retcode;
}
예제 #7
0
파일: ntru.c 프로젝트: jl777/libntru
uint8_t ntru_gen_key_pair(const NtruEncParams *params, NtruEncKeyPair *kp, NtruRandContext *rand_ctx) {
    uint16_t N = params->N;
    uint16_t q = params->q;
    uint16_t df1 = params->df1;
#ifndef NTRU_AVOID_HAMMING_WT_PATENT
    uint16_t df2 = params->df2;
    uint16_t df3 = params->df3;
#endif   /* NTRU_AVOID_HAMMING_WT_PATENT */

    NtruIntPoly fq;

    /* choose a random f that is invertible mod q */
#ifndef NTRU_AVOID_HAMMING_WT_PATENT
    if (params->prod_flag) {
        NtruPrivPoly *t = &kp->priv.t;
        t->prod_flag = 1;
        t->poly.prod.N = N;
        kp->priv.q = q;
        for (;;) {
            /* choose random t, find the inverse of 3t+1 */
            if (!ntru_rand_prod(N, df1, df2, df3, df3, &t->poly.prod, rand_ctx))
                return NTRU_ERR_PRNG;
            if (ntru_invert(t, q, &fq))
                break;
        }
    }
    else
#endif   /* NTRU_AVOID_HAMMING_WT_PATENT */
    {
        NtruPrivPoly *t = &kp->priv.t;
        t->prod_flag = 0;
        kp->priv.q = q;
        for (;;) {
            /* choose random t, find the inverse of 3t+1 */
            if (!ntru_rand_tern(N, df1, df1, &t->poly.tern, rand_ctx))
                return NTRU_ERR_PRNG;
            if (ntru_invert(t, q, &fq))
                break;
        }
    }

    /* choose a random g that is invertible mod q */
    NtruPrivPoly g;
    uint16_t dg = N / 3;
    for (;;) {
#ifndef NTRU_AVOID_HAMMING_WT_PATENT
        if (params->prod_flag && !ntru_rand_prod(N, df1, df2, df3, df3, &g.poly.prod, rand_ctx))
            return NTRU_ERR_PRNG;
        if (!params->prod_flag && !ntru_rand_tern(N, dg, dg, &g.poly.tern, rand_ctx))
            return NTRU_ERR_PRNG;
        g.prod_flag = params->prod_flag;
#else
        if (!ntru_rand_tern(N, dg, dg, &g.poly.tern, rand_ctx))
            return NTRU_ERR_PRNG;
        g.prod_flag = 0;
#endif   /* NTRU_AVOID_HAMMING_WT_PATENT */

        if (!NTRU_CHECK_INVERTIBILITY_G)
            break;
        NtruIntPoly gq;
        if (ntru_invert(&g, q, &gq))
            break;
    }

    NtruIntPoly *h = &kp->pub.h;
    if (!ntru_mult_priv(&g, &fq, h, q))
        return NTRU_ERR_PRNG;
    ntru_mult_fac(h, 3);
    ntru_mod(h, q);

    ntru_clear_priv(&g);
    ntru_clear_int(&fq);

    kp->pub.q = q;

    return NTRU_SUCCESS;
}