Example #1
0
static char *
_verify_nettle_rsa(sldns_buffer* buf, unsigned int digest_size, char* sigblock,
                   unsigned int sigblock_len, uint8_t* key, unsigned int keylen)
{
    uint16_t exp_len = 0;
    size_t exp_offset = 0, mod_offset = 0;
    struct rsa_public_key pubkey;
    mpz_t signature;
    int res = 0;

    /* RSA pubkey parsing as per RFC 3110 sec. 2 */
    if( keylen <= 1) {
        return "null RSA key";
    }
    if (key[0] != 0) {
        /* 1-byte length */
        exp_len = key[0];
        exp_offset = 1;
    } else {
        /* 1-byte NUL + 2-bytes exponent length */
        if (keylen < 3) {
            return "incorrect RSA key length";
        }
        exp_len = READ_UINT16(key+1);
        if (exp_len == 0)
            return "null RSA exponent length";
        exp_offset = 3;
    }
    /* Check that we are not over-running input length */
    if (keylen < exp_offset + exp_len + 1) {
        return "RSA key content shorter than expected";
    }
    mod_offset = exp_offset + exp_len;
    nettle_rsa_public_key_init(&pubkey);
    pubkey.size = keylen - mod_offset;
    nettle_mpz_set_str_256_u(pubkey.e, exp_len, &key[exp_offset]);
    nettle_mpz_set_str_256_u(pubkey.n, pubkey.size, &key[mod_offset]);

    /* Digest content of "buf" and verify its RSA signature in "sigblock"*/
    nettle_mpz_init_set_str_256_u(signature, sigblock_len, (uint8_t*)sigblock);
    switch (digest_size) {
    case SHA1_DIGEST_SIZE:
    {
        uint8_t digest[SHA1_DIGEST_SIZE];
        res = _digest_nettle(SHA1_DIGEST_SIZE, (unsigned char*)sldns_buffer_begin(buf),
                             (unsigned int)sldns_buffer_limit(buf), (unsigned char*)digest);
        res &= rsa_sha1_verify_digest(&pubkey, digest, signature);
        break;
    }
    case SHA256_DIGEST_SIZE:
    {
        uint8_t digest[SHA256_DIGEST_SIZE];
        res = _digest_nettle(SHA256_DIGEST_SIZE, (unsigned char*)sldns_buffer_begin(buf),
                             (unsigned int)sldns_buffer_limit(buf), (unsigned char*)digest);
        res &= rsa_sha256_verify_digest(&pubkey, digest, signature);
        break;
    }
    case SHA512_DIGEST_SIZE:
    {
        uint8_t digest[SHA512_DIGEST_SIZE];
        res = _digest_nettle(SHA512_DIGEST_SIZE, (unsigned char*)sldns_buffer_begin(buf),
                             (unsigned int)sldns_buffer_limit(buf), (unsigned char*)digest);
        res &= rsa_sha512_verify_digest(&pubkey, digest, signature);
        break;
    }
    default:
        break;
    }

    /* Clear and return */
    nettle_rsa_public_key_clear(&pubkey);
    mpz_clear(signature);
    if (!res) {
        return "RSA signature verification failed";
    } else {
        return NULL;
    }
}
Example #2
0
int
_dsa_validate_dss_pq(struct dsa_params *pub,
		     struct dss_params_validation_seeds *cert)
{
	int ret;
	unsigned p_bits, q_bits;
	struct dsa_params pub2;
	struct dss_params_validation_seeds cert2;
	mpz_t r, s;

	p_bits = mpz_sizeinbase(pub->p, 2);
	q_bits = mpz_sizeinbase(pub->q, 2);

	ret = _dsa_check_qp_sizes(q_bits, p_bits, 0);
	if (ret == 0) {
		return 0;
	}

	mpz_init(r);
	mpz_init(s);
	dsa_params_init(&pub2);

	nettle_mpz_set_str_256_u(s, cert->seed_length, cert->seed);

	/* firstseed < 2^(N-1) */
	mpz_set_ui(r, 1);
	mpz_mul_2exp(r, r, q_bits - 1);

	if (mpz_cmp(s, r) < 0) {
		goto fail;
	}

	/* 2^N <= q */
	mpz_set_ui(r, 1);
	mpz_mul_2exp(r, r, q_bits);

	if (mpz_cmp(r, pub->q) <= 0) {
		goto fail;
	}

	/* 2^L <= p */
	mpz_set_ui(r, 1);
	mpz_mul_2exp(r, r, p_bits);

	if (mpz_cmp(r, pub->p) <= 0) {
		goto fail;
	}

	/* p-1 mod q != 0 */
	mpz_set(r, pub->p);
	mpz_sub_ui(r, r, 1);

	mpz_mod(r, r, pub->q);
	if (mpz_cmp_ui(r, 0) != 0) {
		goto fail;
	}

	/* replay the construction */
	ret = _dsa_generate_dss_pq(&pub2, &cert2, cert->seed_length, cert->seed,
				   NULL, NULL, p_bits, q_bits);
	if (ret == 0) {
		goto fail;
	}

	if ((cert->pseed_length > 0 && cert->pseed_length != cert2.pseed_length)
	    || (cert->qseed_length > 0
		&& cert->qseed_length != cert2.qseed_length)
	    || (cert->pgen_counter > 0
		&& cert->pgen_counter != cert2.pgen_counter)
	    || (cert->qgen_counter > 0
		&& cert->qgen_counter != cert2.qgen_counter)
	    || (cert->qseed_length > 0
		&& memcmp(cert->qseed, cert2.qseed, cert2.qseed_length) != 0)
	    || (cert->pseed_length > 0
		&& memcmp(cert->pseed, cert2.pseed, cert2.pseed_length) != 0)) {
		goto fail;
	}

	if (mpz_cmp(pub->q, pub2.q) != 0) {
		goto fail;
	}

	if (mpz_cmp(pub->p, pub2.p) != 0) {
		goto fail;
	}

	if (mpz_sizeinbase(s, 2) < q_bits - 1) {
		goto fail;
	}

	ret = 1;
	goto finish;

 fail:
	ret = 0;

 finish:
	dsa_params_clear(&pub2);
	mpz_clear(r);
	mpz_clear(s);

	return ret;
}
Example #3
0
static char *
_verify_nettle_dsa(sldns_buffer* buf, unsigned char* sigblock,
                   unsigned int sigblock_len, unsigned char* key, unsigned int keylen)
{
    uint8_t digest[SHA1_DIGEST_SIZE];
    uint8_t key_t;
    int res = 0;
    size_t offset;
    struct dsa_public_key pubkey;
    struct dsa_signature signature;
    unsigned int expected_len;

    /* Extract DSA signature from the record */
    nettle_dsa_signature_init(&signature);
    /* Signature length: 41 bytes - RFC 2536 sec. 3 */
    if(sigblock_len == 41) {
        if(key[0] != sigblock[0])
            return "invalid T value in DSA signature or pubkey";
        nettle_mpz_set_str_256_u(signature.r, 20, sigblock+1);
        nettle_mpz_set_str_256_u(signature.s, 20, sigblock+1+20);
    } else {
        /* DER encoded, decode the ASN1 notated R and S bignums */
        /* SEQUENCE { r INTEGER, s INTEGER } */
        struct asn1_der_iterator i, seq;
        if(asn1_der_iterator_first(&i, sigblock_len,
                                   (uint8_t*)sigblock) != ASN1_ITERATOR_CONSTRUCTED
                || i.type != ASN1_SEQUENCE)
            return "malformed DER encoded DSA signature";
        /* decode this element of i using the seq iterator */
        if(asn1_der_decode_constructed(&i, &seq) !=
                ASN1_ITERATOR_PRIMITIVE || seq.type != ASN1_INTEGER)
            return "malformed DER encoded DSA signature";
        if(!asn1_der_get_bignum(&seq, signature.r, 20*8))
            return "malformed DER encoded DSA signature";
        if(asn1_der_iterator_next(&seq) != ASN1_ITERATOR_PRIMITIVE
                || seq.type != ASN1_INTEGER)
            return "malformed DER encoded DSA signature";
        if(!asn1_der_get_bignum(&seq, signature.s, 20*8))
            return "malformed DER encoded DSA signature";
        if(asn1_der_iterator_next(&i) != ASN1_ITERATOR_END)
            return "malformed DER encoded DSA signature";
    }

    /* Validate T values constraints - RFC 2536 sec. 2 & sec. 3 */
    key_t = key[0];
    if (key_t > 8) {
        return "invalid T value in DSA pubkey";
    }

    /* Pubkey minimum length: 21 bytes - RFC 2536 sec. 2 */
    if (keylen < 21) {
        return "DSA pubkey too short";
    }

    expected_len =   1 +		/* T */
                     20 +		/* Q */
                     (64 + key_t*8) +	/* P */
                     (64 + key_t*8) +	/* G */
                     (64 + key_t*8);	/* Y */
    if (keylen != expected_len ) {
        return "invalid DSA pubkey length";
    }

    /* Extract DSA pubkey from the record */
    nettle_dsa_public_key_init(&pubkey);
    offset = 1;
    nettle_mpz_set_str_256_u(pubkey.q, 20, key+offset);
    offset += 20;
    nettle_mpz_set_str_256_u(pubkey.p, (64 + key_t*8), key+offset);
    offset += (64 + key_t*8);
    nettle_mpz_set_str_256_u(pubkey.g, (64 + key_t*8), key+offset);
    offset += (64 + key_t*8);
    nettle_mpz_set_str_256_u(pubkey.y, (64 + key_t*8), key+offset);

    /* Digest content of "buf" and verify its DSA signature in "sigblock"*/
    res = _digest_nettle(SHA1_DIGEST_SIZE, (unsigned char*)sldns_buffer_begin(buf),
                         (unsigned int)sldns_buffer_limit(buf), (unsigned char*)digest);
    res &= dsa_sha1_verify_digest(&pubkey, digest, &signature);

    /* Clear and return */
    nettle_dsa_signature_clear(&signature);
    nettle_dsa_public_key_clear(&pubkey);
    if (!res)
        return "DSA signature verification failed";
    else
        return NULL;
}
Example #4
0
static void
dsa_nist_gen(mpz_t p, mpz_t q,
	     void *random_ctx, nettle_random_func random,
	     void *progress_ctx, nettle_progress_func progress,
	     unsigned L)
{
  unsigned n;
  unsigned b;
  mpz_t s;
  mpz_t t;
  mpz_t c;

  /* For NIS keysizes, we should have L = 512 + 64 * l */
  n = (L-1) / 160; b = (L-1) % 160;

  mpz_init(s);
  mpz_init(t);
  mpz_init(c);
  
  for (;;)
    {
      { /* Generate q */
	uint8_t h1[SHA1_DIGEST_SIZE];
	uint8_t h2[SHA1_DIGEST_SIZE];

	if (progress)
	  progress(progress_ctx, '.');
	
	nettle_mpz_random_size(s, random_ctx, random, SEED_BITS);
	
	hash(s, h1);
	
	mpz_set(t, s);
	mpz_add_ui(t, t, 1);
	
	hash(t, h2);
	
	memxor(h1, h2, SHA1_DIGEST_SIZE);
	
	h1[0] |= 0x80;
	h1[SHA1_DIGEST_SIZE - 1] |= 1;

	nettle_mpz_set_str_256_u(q, SHA1_DIGEST_SIZE, h1);

	/* The spec says that we should use 18 iterations of
	 * miller-rabin. For performance, we want to do some trial
	 * divisions first. The curent version of mpz_probab_prime_p
	 * does exactly that. */
	if (!mpz_probab_prime_p(q, 18))
	  /* Try new seed. */
	  continue;
      }
      /* q is a prime, with overwhelming probability. */

      if (progress)
	progress(progress_ctx, '\n');
      
      {
	/* Official maximum key size: L = 1024 => n = 6 */
	TMP_DECL(buffer, uint8_t, (6 + 1) * SHA1_DIGEST_SIZE);
	unsigned size = (n+1) * SHA1_DIGEST_SIZE;
	unsigned i, j;

	TMP_ALLOC(buffer, size);
	
	for (i = 0, j = 2; i<4096; i++, j+= n+1)
	  {
	    unsigned k;

	    if (progress)
	      progress(progress_ctx, ',');
	    for (k = 0; k<=n ; k++)
	      {
		mpz_set(t, s);
		mpz_add_ui(t, t, j + k);
		hash(t, buffer + ( (n-k) * SHA1_DIGEST_SIZE));
	      }
	    nettle_mpz_set_str_256_u(p, size, buffer);

	    mpz_fdiv_r_2exp(p, p, L);
	    mpz_setbit(p, L-1);

	    mpz_set(t, q);
	    mpz_mul_2exp(t, t, 1);

	    mpz_fdiv_r(c, p, t);

	    mpz_sub_ui(c, c, 1);

	    mpz_sub(p, p, c);

	    if (mpz_probab_prime_p(p, 5))
	      {
		/* Done! */
		if (progress)
		  progress(progress_ctx, '\n');
		
		mpz_clear(s);
		mpz_clear(t);
		mpz_clear(c);

		return;
	      }
	  }
	if (progress)
	  progress(progress_ctx, '+');
      }
    }
}