Example #1
0
/* decode of RSA pubkey chunk
 * - format specified in RFC 2537 RSA/MD5 Keys and SIGs in the DNS
 * - exponent length in bytes (1 or 3 octets)
 *   + 1 byte if in [1, 255]
 *   + otherwise 0x00 followed by 2 bytes of length
 * - exponent
 * - modulus
 */
err_t
unpack_RSA_public_key(struct RSA_public_key *rsa, const chunk_t *pubkey)
{
    chunk_t exponent;
    chunk_t mod;

    rsa->keyid[0] = '\0';	/* in case of keybolbtoid failure */

    if (pubkey->len < 3)
	return "RSA public key blob way to short";	/* not even room for length! */

    rsa->key_rfc3110 = chunk_clone(*pubkey, "rfc3110 format of public key");

    if (pubkey->ptr[0] != 0x00)
    {
	setchunk(exponent, pubkey->ptr + 1, pubkey->ptr[0]);
    }
    else
    {
	setchunk(exponent, pubkey->ptr + 3
	    , (pubkey->ptr[1] << BITS_PER_BYTE) + pubkey->ptr[2]);
    }

    if (pubkey->len - (exponent.ptr - pubkey->ptr) < exponent.len + RSA_MIN_OCTETS_RFC)
	return "RSA public key blob too short";

    mod.ptr = exponent.ptr + exponent.len;
    mod.len = &pubkey->ptr[pubkey->len] - mod.ptr;

    if (mod.len < RSA_MIN_OCTETS)
	return RSA_MIN_OCTETS_UGH;

    if (mod.len > RSA_MAX_OCTETS)
	return RSA_MAX_OCTETS_UGH;

    if (mod.len > pubkey->ptr + pubkey->len - mod.ptr)
       return "RSA public key blob too short";

    n_to_mpz(&rsa->e, exponent.ptr, exponent.len);
    n_to_mpz(&rsa->n, mod.ptr, mod.len);

    keyblobtoid(pubkey->ptr, pubkey->len, rsa->keyid, sizeof(rsa->keyid));

    rsa->k = mpz_sizeinbase(&rsa->n, 2);	/* size in bits, for a start */
    rsa->k = (rsa->k + BITS_PER_BYTE - 1) / BITS_PER_BYTE;	/* now octets */

    if (rsa->k != mod.len)
    {
	mpz_clear(&rsa->e);
	mpz_clear(&rsa->n);
	return "RSA modulus shorter than specified";
    }

    return NULL;
}
Example #2
0
/*
 * Processing FOR KE values.
 */
void
unpack_KE(struct state *st
	  , struct pluto_crypto_req *r
	  , chunk_t *g)
{
    struct pcr_kenonce *kn = &r->pcr_d.kn;

    if (!st->st_sec_in_use)
    {
	st->st_sec_in_use = TRUE;
	freeanychunk(*g);	/* happens in odd error cases */

	clonetochunk(*g, wire_chunk_ptr(kn, &(kn->gi))
		     , kn->gi.len, "saved gi value");
#ifdef HAVE_LIBNSS
	DBG(DBG_CRYPT, DBG_log("saving DH priv (local secret) and pub key into state struc"));
	clonetochunk(st->st_sec_chunk
		     , wire_chunk_ptr(kn, &(kn->secret))
		     , kn->secret.len, "pointer to DH private key (secret)");

	clonetochunk(st->pubk
		     , wire_chunk_ptr(kn, &(kn->pubk))
		     , kn->pubk.len, "pointer to DH public key");
#else
	n_to_mpz(&st->st_sec
		 , wire_chunk_ptr(kn, &(kn->secret))
		 , kn->secret.len);
	clonetochunk(st->st_sec_chunk
		     , wire_chunk_ptr(kn, &(kn->secret))
		     , kn->secret.len, "long term secret");
#endif
    }
}
Example #3
0
/** Compute DH shared secret from our local secret and the peer's public value.
 * We make the leap that the length should be that of the group
 * (see quoted passage at start of ACCEPT_KE).
 */
static void
calc_dh_shared(chunk_t *shared, const chunk_t g
	       , const MP_INT *sec
	       , const struct oakley_group_desc *group)
{
    MP_INT mp_g, mp_shared;
    struct timeval tv0, tv1;
    unsigned long tv_diff;

    gettimeofday(&tv0, NULL);
    n_to_mpz(&mp_g, g.ptr, g.len);
    mpz_init(&mp_shared);
    mpz_powm(&mp_shared, &mp_g, sec, group->modulus);
    mpz_clear(&mp_g);

    *shared = mpz_to_n(&mp_shared, group->bytes);
    mpz_clear(&mp_shared);

    gettimeofday(&tv1, NULL);
    tv_diff=(tv1.tv_sec  - tv0.tv_sec) * 1000000 + (tv1.tv_usec - tv0.tv_usec);
    DBG(DBG_CRYPT, 
    	DBG_log("calc_dh_shared(): time elapsed (%s): %ld usec"
		, enum_show(&oakley_group_names, group->group)
		, tv_diff);
       );
Example #4
0
void calc_ke(struct pluto_crypto_req *r)
{
    MP_INT mp_g;
    MP_INT secret;
    chunk_t gi;
    struct pcr_kenonce *kn = &r->pcr_d.kn;
    const struct oakley_group_desc *group;

    group = lookup_group(kn->oakley_group);

    pluto_crypto_allocchunk(&kn->thespace
			    , &kn->secret
			    , LOCALSECRETSIZE);

    get_rnd_bytes(wire_chunk_ptr(kn, &(kn->secret)), LOCALSECRETSIZE);

    n_to_mpz(&secret, wire_chunk_ptr(kn, &(kn->secret)), LOCALSECRETSIZE);

    mpz_init(&mp_g);

    oswcrypto.mod_exp(&mp_g, group->generator, &secret, group->modulus);

    gi = mpz_to_n(&mp_g, group->bytes);

    pluto_crypto_allocchunk(&kn->thespace, &kn->gi, gi.len);

    {
	char *gip = wire_chunk_ptr(kn, &(kn->gi));

	memcpy(gip, gi.ptr, gi.len);
    }

    DBG(DBG_CRYPT,
	DBG_dump("Local DH secret:\n"
		 , wire_chunk_ptr(kn, &(kn->secret))
		 , LOCALSECRETSIZE);
	DBG_dump_chunk("Public DH value sent:\n", gi));

    /* clean up after ourselves */
    mpz_clear(&mp_g);
    mpz_clear(&secret);
    freeanychunk(gi);
}
Example #5
0
/*
 * Processing FOR KE values.
 */
void
unpack_KE(struct state *st
	  , struct pluto_crypto_req *r
	  , chunk_t *g)
{
    struct pcr_kenonce *kn = &r->pcr_d.kn;

    if (!st->st_sec_in_use)
    {
	st->st_sec_in_use = TRUE;
	freeanychunk(*g);	/* happens in odd error cases */
	
	clonetochunk(*g, wire_chunk_ptr(kn, &(kn->gi))
		     , kn->gi.len, "saved gi value");

	n_to_mpz(&st->st_sec
		 , wire_chunk_ptr(kn, &(kn->secret))
		 , kn->secret.len);
	clonetochunk(st->st_sec_chunk
		     , wire_chunk_ptr(kn, &(kn->secret))
		     , kn->secret.len, "long term secret");
    }
}
Example #6
0
err_t
try_RSA_signature_v2(const u_char hash_val[MAX_DIGEST_LEN]
		     , size_t hash_len
		     , const pb_stream *sig_pbs, struct pubkey *kr
		     , struct state *st)
{
    const u_char *sig_val = sig_pbs->cur;
    size_t sig_len = pbs_left(sig_pbs);
    u_char s[RSA_MAX_OCTETS];	/* for decrypted sig_val */
    u_char *sig;
    unsigned int padlen;
    const struct RSA_public_key *k = &kr->u.rsa;

    if (k == NULL)
	return "1""no key available";	/* failure: no key to use */

    /* decrypt the signature -- reversing RSA_sign_hash */
    if (sig_len != k->k)
    {
        DBG_log("sig_len: %u != k->k: %u"
                , (unsigned int)sig_len, (unsigned int)k->k);
	return "1""SIG length does not match public key length";
    }

    /* actual exponentiation; see PKCS#1 v2.0 5.1 */
    {
	chunk_t temp_s;
	MP_INT c;

	n_to_mpz(&c, sig_val, sig_len);
	oswcrypto.mod_exp(&c, &c, &k->e, &k->n);

	temp_s = mpz_to_n(&c, sig_len);	/* back to octets */
	memcpy(s, temp_s.ptr, sig_len);
	pfree(temp_s.ptr);
	mpz_clear(&c);
    }

    /* check signature contents */
    /* verify padding */
    padlen = sig_len - 3 - (hash_len+der_digestinfo_len);
    /* now check padding */
    sig = s;

    DBG(DBG_CRYPT,
	DBG_dump("v2rsa decrypted SIG1:", sig, sig_len));

    if(sig[0]    != 0x00
       || sig[1] != 0x01
       || sig[padlen+2] != 0x00) {
	return "2""SIG padding does not check out";
    }

    /* skip padding */
    sig += padlen+3;

    /* 2 verify that the has was done with SHA1 */
    if(memcmp(der_digestinfo, sig, der_digestinfo_len)!=0) {
	return "SIG not performed with SHA1";
    }

    sig += der_digestinfo_len;

    DBG(DBG_CRYPT,
	DBG_dump("v2rsa decrypted SIG:", hash_val, hash_len);
	DBG_dump("v2rsa computed hash:", sig, hash_len);
    );
Example #7
0
void calc_ke(struct pluto_crypto_req *r)
{
#ifndef HAVE_LIBNSS
    MP_INT mp_g;
    MP_INT secret;
    chunk_t gi;
#else
    chunk_t  prime;
    chunk_t  base;
    SECKEYDHParams      dhp;
    PK11SlotInfo *slot = NULL;
    SECKEYPrivateKey *privk;
    SECKEYPublicKey   *pubk;
#endif
    struct pcr_kenonce *kn = &r->pcr_d.kn;
    const struct oakley_group_desc *group;

    group = lookup_group(kn->oakley_group);

#ifndef HAVE_LIBNSS
    pluto_crypto_allocchunk(&kn->thespace
			    , &kn->secret
			    , LOCALSECRETSIZE);

    get_rnd_bytes(wire_chunk_ptr(kn, &(kn->secret)), LOCALSECRETSIZE);

    n_to_mpz(&secret, wire_chunk_ptr(kn, &(kn->secret)), LOCALSECRETSIZE);

    mpz_init(&mp_g);

#ifdef USE_MODP_RFC5114
    oswcrypto.mod_exp(&mp_g, group->generator, &secret, group->modulus);
#else
    oswcrypto.mod_exp(&mp_g, &groupgenerator, &secret, group->modulus);
#endif

    gi = mpz_to_n(&mp_g, group->bytes);

    pluto_crypto_allocchunk(&kn->thespace, &kn->gi, gi.len);

    {
	char *gip = wire_chunk_ptr(kn, &(kn->gi));

	memcpy(gip, gi.ptr, gi.len);
    }

    DBG(DBG_CRYPT,
	DBG_dump("Local DH secret:\n"
		 , wire_chunk_ptr(kn, &(kn->secret))
		 , LOCALSECRETSIZE);
	DBG_dump_chunk("Public DH value sent:\n", gi));

    /* clean up after ourselves */
    mpz_clear(&mp_g);
    mpz_clear(&secret);
    freeanychunk(gi);
#else

#ifdef USE_MODP_RFC5114
    base  = mpz_to_n2(group->generator);
#else
    base  = mpz_to_n2(&groupgenerator);
#endif
    prime = mpz_to_n2(group->modulus);

    DBG(DBG_CRYPT,DBG_dump_chunk("NSS: Value of Prime:\n", prime));
    DBG(DBG_CRYPT,DBG_dump_chunk("NSS: Value of base:\n", base));

    dhp.prime.data=prime.ptr;
    dhp.prime.len=prime.len;
    dhp.base.data=base.ptr;
    dhp.base.len=base.len;

    slot = PK11_GetBestSlot(CKM_DH_PKCS_KEY_PAIR_GEN,osw_return_nss_password_file_info());
    if(!slot) {
	loglog(RC_LOG_SERIOUS, "NSS: slot for DH key gen is NULL");
    }
    PR_ASSERT(slot!=NULL);

    while(1) {
	privk = PK11_GenerateKeyPair(slot, CKM_DH_PKCS_KEY_PAIR_GEN, &dhp, &pubk, PR_FALSE, PR_TRUE, osw_return_nss_password_file_info());
	if(!privk) {
	   loglog(RC_LOG_SERIOUS, "NSS: DH private key creation failed (err %d)", PR_GetError());
	}
	PR_ASSERT(privk!=NULL);

	if( group-> bytes == pubk->u.dh.publicValue.len ) {
	   DBG(DBG_CRYPT, DBG_log("NSS: generated dh priv and pub keys: %d\n", pubk->u.dh.publicValue.len));
	   break;
	} else {
	   DBG(DBG_CRYPT, DBG_log("NSS: generating dh priv and pub keys"));
	   if (privk) SECKEY_DestroyPrivateKey(privk);
	   if (pubk)  SECKEY_DestroyPublicKey(pubk);
	   }
    }

    pluto_crypto_allocchunk(&kn->thespace, &kn->secret, sizeof(SECKEYPrivateKey*));
    {
	char *gip = wire_chunk_ptr(kn, &(kn->secret));
	memcpy(gip, &privk, sizeof(SECKEYPrivateKey *));
    }

    pluto_crypto_allocchunk(&kn->thespace, &kn->gi, pubk->u.dh.publicValue.len);
    {
	char *gip = wire_chunk_ptr(kn, &(kn->gi));
	memcpy(gip, pubk->u.dh.publicValue.data, pubk->u.dh.publicValue.len);
    }

    pluto_crypto_allocchunk(&kn->thespace, &kn->pubk, sizeof(SECKEYPublicKey*));
    {
	char *gip = wire_chunk_ptr(kn, &(kn->pubk));
	memcpy(gip, &pubk, sizeof(SECKEYPublicKey*));
    }

    DBG(DBG_CRYPT,
       DBG_dump("NSS: Local DH secret:\n"
                , wire_chunk_ptr(kn, &(kn->secret))
                , sizeof(SECKEYPrivateKey*));
       DBG_dump("NSS: Public DH value sent(computed in NSS):\n", wire_chunk_ptr(kn, &(kn->gi)),pubk->u.dh.publicValue.len));

    DBG(DBG_CRYPT,
        DBG_dump("NSS: Local DH public value (pointer):\n"
                 , wire_chunk_ptr(kn, &(kn->pubk))
                 , sizeof(SECKEYPublicKey*)));

    /* clean up after ourselves */
    if (slot) {
	PK11_FreeSlot(slot);
    }
    /* if (privk){SECKEY_DestroyPrivateKey(privk);} */
    /* if (pubk){SECKEY_DestroyPublicKey(pubk);} */
    freeanychunk(prime);
    freeanychunk(base);
#endif
}