static void test_bignum(const char *hex, unsigned length, const uint8_t *base256) { mpz_t a; mpz_t b; uint8_t *buf; mpz_init_set_str(a, hex, 16); nettle_mpz_init_set_str_256_s(b, length, base256); if (mpz_cmp(a, b)) FAIL(); buf = xalloc(length + 1); memset(buf, 17, length + 1); nettle_mpz_get_str_256(length, buf, a); if (!MEMEQ(length, buf, base256)) FAIL(); if (buf[length] != 17) FAIL(); mpz_clear(a); mpz_clear(b); free(buf); }
static int extract_digest_info(const struct rsa_public_key *key, gnutls_datum_t * di, uint8_t ** rdi, const mpz_t signature) { unsigned i; int ret; mpz_t m; uint8_t *em; if (key->size == 0) return 0; em = gnutls_malloc(key->size); if (em == NULL) return 0; mpz_init(m); mpz_powm(m, signature, key->e, key->n); nettle_mpz_get_str_256(key->size, em, m); mpz_clear(m); if (em[0] != 0 || em[1] != 1) { ret = 0; goto cleanup; } for (i = 2; i < key->size; i++) { if (em[i] == 0 && i > 2) break; if (em[i] != 0xff) { ret = 0; goto cleanup; } } i++; *rdi = em; di->data = &em[i]; di->size = key->size - i; return 1; cleanup: memset(em, 0, sizeof(key->size)); gnutls_free(em); return ret; }
static int extract_digest_info(const struct rsa_public_key *key, unsigned *length, uint8_t *digest_info, const mpz_t signature) { unsigned i; int ret; mpz_t m; uint8_t *em; if (key->size == 0 || *length < key->size) return 0; em = gnutls_malloc(key->size); if (em == NULL) return 0; mpz_init (m); mpz_powm(m, signature, key->e, key->n); nettle_mpz_get_str_256(key->size, em, m); mpz_clear(m); if (em[0] != 0 || em[1] != 1) { ret = 0; goto cleanup; } for (i = 2; i < key->size; i++) { if (em[i] == 0 && i > 2) break; if (em[i] != 0xff) { ret = 0; goto cleanup; } } i++; memcpy(digest_info, &em[i], key->size-i); *length = key->size-i; ret = 1; cleanup: gnutls_free(em); return ret; }
int R_SignFinal(R_SIGNATURE_CTX *ctx, uint8_t *signature, unsigned *length, R_RSA_PRIVATE_KEY *key) { struct rsa_private_key k; int res; nettle_mpz_init_set_str_256_u(k.p, MAX_RSA_MODULUS_LEN, key->prime[0]); nettle_mpz_init_set_str_256_u(k.q, MAX_RSA_MODULUS_LEN, key->prime[1]); nettle_mpz_init_set_str_256_u(k.a, MAX_RSA_MODULUS_LEN, key->primeExponent[0]); nettle_mpz_init_set_str_256_u(k.b, MAX_RSA_MODULUS_LEN, key->primeExponent[1]); nettle_mpz_init_set_str_256_u(k.c, MAX_RSA_MODULUS_LEN, key->coefficient); if (rsa_private_key_prepare(&k) && (k.size <= MAX_RSA_MODULUS_LEN)) { mpz_t s; mpz_init(s); if (rsa_md5_sign(&k, &ctx->hash, s)) { nettle_mpz_get_str_256(k.size, signature, s); *length = k.size; res = RE_SUCCESS; } else res = RE_PRIVATE_KEY; mpz_clear(s); } else res = RE_PRIVATE_KEY; mpz_clear(k.p); mpz_clear(k.q); mpz_clear(k.a); mpz_clear(k.b); mpz_clear(k.c); return res; }
int pkcs1_decrypt (size_t key_size, const mpz_t m, size_t *length, uint8_t *message) { TMP_GMP_DECL(em, uint8_t); int ret; TMP_GMP_ALLOC(em, key_size); nettle_mpz_get_str_256(key_size, em, m); ret = _pkcs1_sec_decrypt_variable (length, message, key_size, em); TMP_GMP_FREE(em); return ret; }
static int write_bignum(FILE *f, mpz_t x) { unsigned size = nettle_mpz_sizeinbase_256_u(x); uint8_t *p; int res; if (!write_uint32(f, size)) return 0; p = xalloc(size); nettle_mpz_get_str_256(size, p, x); res = write_string(f, size, p); free(p); return res; }
static void hash(mpz_t x, uint8_t *digest) { mpz_t t; uint8_t data[SEED_LENGTH]; struct sha1_ctx ctx; mpz_init_set(t, x); mpz_fdiv_r_2exp(t, t, SEED_BITS); nettle_mpz_get_str_256(SEED_LENGTH, data, t); mpz_clear(t); sha1_init(&ctx); sha1_update(&ctx, SEED_LENGTH, data); sha1_digest(&ctx, SHA1_DIGEST_SIZE, digest); }
static void ecc_shared_secret(struct ecc_scalar *private_key, struct ecc_point *public_key, void *out, unsigned size) { struct ecc_point r; mpz_t x; mpz_init(x); ecc_point_init(&r, public_key->ecc); ecc_point_mul(&r, private_key, public_key); ecc_point_get(&r, x, NULL); nettle_mpz_get_str_256(size, out, x); mpz_clear(x); ecc_point_clear(&r); return; }
int pgp_put_mpi(struct nettle_buffer *buffer, const mpz_t x) { unsigned bits = mpz_sizeinbase(x, 2); unsigned octets = (bits + 7) / 8; uint8_t *p; /* FIXME: What's the correct representation of zero? */ if (!pgp_put_uint16(buffer, bits)) return 0; p = nettle_buffer_space(buffer, octets); if (!p) return 0; nettle_mpz_get_str_256(octets, p, x); return 1; }
int pkcs1_decrypt (unsigned key_size, const mpz_t m, unsigned *length, uint8_t *message) { TMP_DECL(em, uint8_t, NETTLE_MAX_BIGNUM_SIZE); uint8_t *terminator; unsigned padding; unsigned message_length; TMP_ALLOC(em, key_size); nettle_mpz_get_str_256(key_size, em, m); /* Check format */ if (em[0] || em[1] != 2) return 0; terminator = memchr(em + 2, 0, key_size - 2); if (!terminator) return 0; padding = terminator - (em + 2); if (padding < 8) return 0; message_length = key_size - 3 - padding; if (*length < message_length) return 0; memcpy(message, terminator + 1, message_length); *length = message_length; return 1; }
static int wrap_nettle_mpi_print(const bigint_t a, void *buffer, size_t * nbytes, gnutls_bigint_format_t format) { unsigned int size; mpz_t *p = (void *) a; if (format == GNUTLS_MPI_FORMAT_USG) { size = nettle_mpz_sizeinbase_256_u(*p); } else if (format == GNUTLS_MPI_FORMAT_STD) { size = nettle_mpz_sizeinbase_256_s(*p); #if ENABLE_GOST } else if (format == GNUTLS_MPI_FORMAT_ULE) { size = nettle_mpz_sizeinbase_256_u_le(*p); #endif } else { gnutls_assert(); return GNUTLS_E_INVALID_REQUEST; } if (buffer == NULL || size > *nbytes) { *nbytes = size; gnutls_assert(); return GNUTLS_E_SHORT_MEMORY_BUFFER; } #if ENABLE_GOST if (format == GNUTLS_MPI_FORMAT_ULE) nettle_mpz_get_str_256_u_le(size, buffer, *p); else #endif nettle_mpz_get_str_256(size, buffer, *p); *nbytes = size; return 0; }
static int rsa_provable_prime (mpz_t p, unsigned *prime_seed_length, void *prime_seed, unsigned bits, unsigned seed_length, const void *seed, mpz_t e, void *progress_ctx, nettle_progress_func * progress) { mpz_t x, t, s, r1, r2, p0, sq; int ret; unsigned pcounter = 0; unsigned iterations; unsigned storage_length = 0, i; uint8_t *storage = NULL; uint8_t pseed[MAX_PVP_SEED_SIZE+1]; unsigned pseed_length = sizeof(pseed), tseed_length; unsigned max = bits*5; mpz_init(p0); mpz_init(sq); mpz_init(x); mpz_init(t); mpz_init(s); mpz_init(r1); mpz_init(r2); /* p1 = p2 = 1 */ ret = st_provable_prime(p0, &pseed_length, pseed, NULL, 1+div_ceil(bits,2), seed_length, seed, progress_ctx, progress); if (ret == 0) { goto cleanup; } iterations = div_ceil(bits, DIGEST_SIZE*8); mpz_set_ui(x, 0); if (iterations > 0) { storage_length = iterations * DIGEST_SIZE; storage = malloc(storage_length); if (storage == NULL) { goto fail; } nettle_mpz_set_str_256_u(s, pseed_length, pseed); for (i = 0; i < iterations; i++) { tseed_length = mpz_seed_sizeinbase_256_u(s, pseed_length); if (tseed_length > sizeof(pseed)) goto fail; nettle_mpz_get_str_256(tseed_length, pseed, s); hash(&storage[(iterations - i - 1) * DIGEST_SIZE], tseed_length, pseed); mpz_add_ui(s, s, 1); } nettle_mpz_set_str_256_u(x, storage_length, storage); } /* x = sqrt(2)*2^(bits-1) + (x mod 2^(bits) - sqrt(2)*2(bits-1)) */ /* sq = sqrt(2)*2^(bits-1) */ mpz_set_ui(r1, 1); mpz_mul_2exp(r1, r1, 2*bits-1); mpz_sqrt(sq, r1); /* r2 = 2^bits - sq */ mpz_set_ui(r2, 1); mpz_mul_2exp(r2, r2, bits); mpz_sub(r2, r2, sq); /* x = sqrt(2)*2^(bits-1) + (x mod (2^L - sqrt(2)*2^(bits-1)) */ mpz_mod(x, x, r2); mpz_add(x, x, sq); /* y = p2 = p1 = 1 */ /* r1 = (2 y p0 p1) */ mpz_mul_2exp(r1, p0, 1); /* r2 = 2 p0 p1 p2 (p2=y=1) */ mpz_set(r2, r1); /* r1 = (2 y p0 p1) + x */ mpz_add(r1, r1, x); /* t = ((2 y p0 p1) + x) / (2 p0 p1 p2) */ mpz_cdiv_q(t, r1, r2); retry: /* p = t p2 - y = t - 1 */ mpz_sub_ui(p, t, 1); /* p = 2(tp2-y)p0p1 */ mpz_mul(p, p, p0); mpz_mul_2exp(p, p, 1); /* p = 2(tp2-y)p0p1 + 1*/ mpz_add_ui(p, p, 1); mpz_set_ui(r2, 1); mpz_mul_2exp(r2, r2, bits); if (mpz_cmp(p, r2) > 0) { /* t = (2 y p0 p1) + sqrt(2)*2^(bits-1) / (2p0p1p2) */ mpz_set(r1, p0); /* r1 = (2 y p0 p1) */ mpz_mul_2exp(r1, r1, 1); /* sq = sqrt(2)*2^(bits-1) */ /* r1 = (2 y p0 p1) + sq */ mpz_add(r1, r1, sq); /* r2 = 2 p0 p1 p2 */ mpz_mul_2exp(r2, p0, 1); /* t = ((2 y p0 p1) + sq) / (2 p0 p1 p2) */ mpz_cdiv_q(t, r1, r2); } pcounter++; /* r2 = p - 1 */ mpz_sub_ui(r2, p, 1); /* r1 = GCD(p1, e) */ mpz_gcd(r1, e, r2); if (mpz_cmp_ui(r1, 1) == 0) { mpz_set_ui(x, 0); /* a = 0 */ if (iterations > 0) { for (i = 0; i < iterations; i++) { tseed_length = mpz_seed_sizeinbase_256_u(s, pseed_length); if (tseed_length > sizeof(pseed)) goto fail; nettle_mpz_get_str_256(tseed_length, pseed, s); hash(&storage[(iterations - i - 1) * DIGEST_SIZE], tseed_length, pseed); mpz_add_ui(s, s, 1); } nettle_mpz_set_str_256_u(x, storage_length, storage); } /* a = 2 + a mod p-3 */ mpz_sub_ui(r1, p, 3); /* p is too large to worry about negatives */ mpz_mod(x, x, r1); mpz_add_ui(x, x, 2); /* z = a^(2(tp2-y)p1) mod p */ /* r1 = (tp2-y) */ mpz_sub_ui(r1, t, 1); /* r1 = 2(tp2-y)p1 */ mpz_mul_2exp(r1, r1, 1); /* z = r2 = a^r1 mod p */ mpz_powm(r2, x, r1, p); mpz_sub_ui(r1, r2, 1); mpz_gcd(x, r1, p); if (mpz_cmp_ui(x, 1) == 0) { mpz_powm(r1, r2, p0, p); if (mpz_cmp_ui(r1, 1) == 0) { if (prime_seed_length != NULL) { tseed_length = mpz_seed_sizeinbase_256_u(s, pseed_length); if (tseed_length > sizeof(pseed)) goto fail; nettle_mpz_get_str_256(tseed_length, pseed, s); if (*prime_seed_length < tseed_length) { *prime_seed_length = tseed_length; goto fail; } *prime_seed_length = tseed_length; if (prime_seed != NULL) memcpy(prime_seed, pseed, tseed_length); } ret = 1; goto cleanup; } } } if (pcounter >= max) { goto fail; } mpz_add_ui(t, t, 1); goto retry; fail: ret = 0; cleanup: free(storage); mpz_clear(p0); mpz_clear(sq); mpz_clear(r1); mpz_clear(r2); mpz_clear(x); mpz_clear(t); mpz_clear(s); return ret; }