/* Do DSA signature calculation. params is p, q, g, y, x in that order. */ int _gnutls_dsa_sign (gnutls_datum_t * signature, const gnutls_datum_t * hash, bigint_t * params, unsigned int params_len) { int ret; size_t i; size_t k; gnutls_pk_params_st pk_params; for (i = 0; i < params_len; i++) pk_params.params[i] = params[i]; pk_params.params_nr = params_len; k = hash->size; if (k < 20) { /* SHA1 or better only */ gnutls_assert (); return GNUTLS_E_PK_SIGN_FAILED; } ret = _gnutls_pk_sign (GNUTLS_PK_DSA, signature, hash, &pk_params); /* rs[0], rs[1] now hold r,s */ if (ret < 0) { gnutls_assert (); return ret; } return 0; }
/*- * gnutls_privkey_sign_raw_data: * @key: Holds the key * @flags: should be zero * @data: holds the data to be signed * @signature: will contain the signature allocated with gnutls_malloc() * * This function will sign the given data using a signature algorithm * supported by the private key. Note that this is a low-level function * and does not apply any preprocessing or hash on the signed data. * For example on an RSA key the input @data should be of the DigestInfo * PKCS #1 1.5 format. Use it only if you know what are you doing. * * Note this function is equivalent to using the %GNUTLS_PRIVKEY_SIGN_FLAG_TLS1_RSA * flag with gnutls_privkey_sign_hash(). * * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a * negative error value. * * Since: 3.1.10 -*/ static int _gnutls_privkey_sign_raw_data(gnutls_privkey_t key, unsigned flags, const gnutls_datum_t * data, gnutls_datum_t * signature) { switch (key->type) { #ifdef ENABLE_OPENPGP case GNUTLS_PRIVKEY_OPENPGP: return gnutls_openpgp_privkey_sign_hash(key->key.openpgp, data, signature); #endif #ifdef ENABLE_PKCS11 case GNUTLS_PRIVKEY_PKCS11: return _gnutls_pkcs11_privkey_sign_hash(key->key.pkcs11, data, signature); #endif case GNUTLS_PRIVKEY_X509: return _gnutls_pk_sign(key->key.x509->pk_algorithm, signature, data, &key->key.x509->params); case GNUTLS_PRIVKEY_EXT: if (key->key.ext.sign_func == NULL) return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); return key->key.ext.sign_func(key, key->key.ext.userdata, data, signature); default: gnutls_assert(); return GNUTLS_E_INVALID_REQUEST; } }
/* Do DSA signature calculation. params is p, q, g, y, x in that order. */ int _gnutls_dsa_sign (gnutls_datum_t * signature, const gnutls_datum_t * hash, mpi_t * params, unsigned params_len) { mpi_t rs[2], mdata; int ret; size_t k; k = hash->size; if (k != 20) { /* SHA only */ gnutls_assert (); return GNUTLS_E_PK_SIGN_FAILED; } if (_gnutls_mpi_scan_nz (&mdata, hash->data, &k) != 0) { gnutls_assert (); return GNUTLS_E_MPI_SCAN_FAILED; } ret = _gnutls_pk_sign (GCRY_PK_DSA, rs, mdata, params, params_len); /* rs[0], rs[1] now hold r,s */ _gnutls_mpi_release (&mdata); if (ret < 0) { gnutls_assert (); return ret; } ret = encode_ber_rs (signature, rs[0], rs[1]); /* free r,s */ _gnutls_mpi_release (&rs[0]); _gnutls_mpi_release (&rs[1]); if (ret != 0) { gnutls_assert (); return GNUTLS_E_MEMORY_ERROR; } return 0; }
/*- * _gnutls_x509_privkey_sign_hash2: * @signer: Holds the signer's key * @hash_algo: The hash algorithm used * @hash_data: holds the data to be signed * @signature: will contain newly allocated signature * @flags: (0) for now * * This function will sign the given hashed data using a signature algorithm * supported by the private key. Signature algorithms are always used * together with a hash functions. Different hash functions may be * used for the RSA algorithm, but only SHA-1,SHA-224 and SHA-256 * for the DSA keys, depending on their bit size. * * Use gnutls_x509_crt_get_preferred_hash_algorithm() to determine * the hash algorithm. * * The RSA algorithm is used in PKCS #1 v1.5 mode. * * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a * negative error value. -*/ static int _gnutls_x509_privkey_sign_hash2 (gnutls_x509_privkey_t signer, gnutls_digest_algorithm_t hash_algo, unsigned int flags, const gnutls_datum_t * hash_data, gnutls_datum_t * signature) { int ret; gnutls_datum_t digest; digest.data = gnutls_malloc (hash_data->size); if (digest.data == NULL) { gnutls_assert (); return GNUTLS_E_MEMORY_ERROR; } digest.size = hash_data->size; memcpy (digest.data, hash_data->data, digest.size); ret = pk_prepare_hash (signer->pk_algorithm, hash_algo, &digest); if (ret < 0) { gnutls_assert (); goto cleanup; } ret = _gnutls_pk_sign (signer->pk_algorithm, signature, &digest, &signer->params); if (ret < 0) { gnutls_assert (); goto cleanup; } ret = 0; cleanup: _gnutls_free_datum (&digest); return ret; }
/** * gnutls_x509_privkey_sign_hash: * @key: Holds the key * @hash: holds the data to be signed * @signature: will contain newly allocated signature * * This function will sign the given hash using the private key. Do not * use this function directly unless you know what it is. Typical signing * requires the data to be hashed and stored in special formats * (e.g. BER Digest-Info for RSA). * * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a * negative error value. * * Deprecated in: 2.12.0 */ int gnutls_x509_privkey_sign_hash (gnutls_x509_privkey_t key, const gnutls_datum_t * hash, gnutls_datum_t * signature) { int result; if (key == NULL) { gnutls_assert (); return GNUTLS_E_INVALID_REQUEST; } result = _gnutls_pk_sign (key->pk_algorithm, signature, hash, &key->params); if (result < 0) { gnutls_assert (); return result; } return 0; }
/* Do PKCS-1 RSA encryption. * params is modulus, public exp. */ int _gnutls_pkcs1_rsa_encrypt (gnutls_datum_t * ciphertext, const gnutls_datum_t * plaintext, mpi_t * params, unsigned params_len, unsigned btype) { unsigned int i, pad; int ret; mpi_t m, res; opaque *edata, *ps; size_t k, psize; size_t mod_bits; mod_bits = _gnutls_mpi_get_nbits (params[0]); k = mod_bits / 8; if (mod_bits % 8 != 0) k++; if (plaintext->size > k - 11) { gnutls_assert (); return GNUTLS_E_PK_ENCRYPTION_FAILED; } edata = gnutls_alloca (k); if (edata == NULL) { gnutls_assert (); return GNUTLS_E_MEMORY_ERROR; } /* EB = 00||BT||PS||00||D * (use block type 'btype') */ edata[0] = 0; edata[1] = btype; psize = k - 3 - plaintext->size; ps = &edata[2]; switch (btype) { case 2: /* using public key */ if (params_len < RSA_PUBLIC_PARAMS) { gnutls_assert (); gnutls_afree (edata); return GNUTLS_E_INTERNAL_ERROR; } if (gc_pseudo_random (ps, psize) != GC_OK) { gnutls_assert (); gnutls_afree (edata); return GNUTLS_E_RANDOM_FAILED; } for (i = 0; i < psize; i++) while (ps[i] == 0) { if (gc_pseudo_random (&ps[i], 1) != GC_OK) { gnutls_assert (); gnutls_afree (edata); return GNUTLS_E_RANDOM_FAILED; } } break; case 1: /* using private key */ if (params_len < RSA_PRIVATE_PARAMS) { gnutls_assert (); gnutls_afree (edata); return GNUTLS_E_INTERNAL_ERROR; } for (i = 0; i < psize; i++) ps[i] = 0xff; break; default: gnutls_assert (); gnutls_afree (edata); return GNUTLS_E_INTERNAL_ERROR; } ps[psize] = 0; memcpy (&ps[psize + 1], plaintext->data, plaintext->size); if (_gnutls_mpi_scan_nz (&m, edata, &k) != 0) { gnutls_assert (); gnutls_afree (edata); return GNUTLS_E_MPI_SCAN_FAILED; } gnutls_afree (edata); if (btype == 2) /* encrypt */ ret = _gnutls_pk_encrypt (GCRY_PK_RSA, &res, m, params, params_len); else /* sign */ ret = _gnutls_pk_sign (GCRY_PK_RSA, &res, m, params, params_len); _gnutls_mpi_release (&m); if (ret < 0) { gnutls_assert (); return ret; } _gnutls_mpi_print (NULL, &psize, res); if (psize < k) { /* padding psize */ pad = k - psize; psize = k; } else if (psize == k) { pad = 0; } else { /* psize > k !!! */ /* This is an impossible situation */ gnutls_assert (); _gnutls_mpi_release (&res); return GNUTLS_E_INTERNAL_ERROR; } ciphertext->data = gnutls_malloc (psize); if (ciphertext->data == NULL) { gnutls_assert (); _gnutls_mpi_release (&res); return GNUTLS_E_MEMORY_ERROR; } _gnutls_mpi_print (&ciphertext->data[pad], &psize, res); for (i = 0; i < pad; i++) ciphertext->data[i] = 0; ciphertext->size = k; _gnutls_mpi_release (&res); return 0; }
/* Do PKCS-1 RSA encryption. * params is modulus, public exp. */ int _gnutls_pkcs1_rsa_encrypt (gnutls_datum_t * ciphertext, const gnutls_datum_t * plaintext, bigint_t * params, unsigned params_len, unsigned btype) { unsigned int i, pad; int ret; opaque *edata, *ps; size_t k, psize; size_t mod_bits; gnutls_pk_params_st pk_params; gnutls_datum to_encrypt, encrypted; for (i = 0; i < params_len; i++) pk_params.params[i] = params[i]; pk_params.params_nr = params_len; mod_bits = _gnutls_mpi_get_nbits (params[0]); k = mod_bits / 8; if (mod_bits % 8 != 0) k++; if (plaintext->size > k - 11) { gnutls_assert (); return GNUTLS_E_PK_ENCRYPTION_FAILED; } edata = gnutls_malloc (k); if (edata == NULL) { gnutls_assert (); return GNUTLS_E_MEMORY_ERROR; } /* EB = 00||BT||PS||00||D * (use block type 'btype') */ edata[0] = 0; edata[1] = btype; psize = k - 3 - plaintext->size; ps = &edata[2]; switch (btype) { case 2: /* using public key */ if (params_len < RSA_PUBLIC_PARAMS) { gnutls_assert (); gnutls_free (edata); return GNUTLS_E_INTERNAL_ERROR; } ret = _gnutls_rnd (GNUTLS_RND_RANDOM, ps, psize); if (ret < 0) { gnutls_assert (); gnutls_free (edata); return ret; } for (i = 0; i < psize; i++) while (ps[i] == 0) { ret = _gnutls_rnd (GNUTLS_RND_RANDOM, &ps[i], 1); if (ret < 0) { gnutls_assert (); gnutls_free (edata); return ret; } } break; case 1: /* using private key */ if (params_len < RSA_PRIVATE_PARAMS) { gnutls_assert (); gnutls_free (edata); return GNUTLS_E_INTERNAL_ERROR; } for (i = 0; i < psize; i++) ps[i] = 0xff; break; default: gnutls_assert (); gnutls_free (edata); return GNUTLS_E_INTERNAL_ERROR; } ps[psize] = 0; memcpy (&ps[psize + 1], plaintext->data, plaintext->size); to_encrypt.data = edata; to_encrypt.size = k; if (btype == 2) /* encrypt */ ret = _gnutls_pk_encrypt (GNUTLS_PK_RSA, &encrypted, &to_encrypt, &pk_params); else /* sign */ ret = _gnutls_pk_sign (GNUTLS_PK_RSA, &encrypted, &to_encrypt, &pk_params); gnutls_free (edata); if (ret < 0) { gnutls_assert (); return ret; } psize = encrypted.size; if (psize < k) { /* padding psize */ pad = k - psize; psize = k; } else if (psize == k) { /* pad = 0; * no need to do anything else */ ciphertext->data = encrypted.data; ciphertext->size = encrypted.size; return 0; } else { /* psize > k !!! */ /* This is an impossible situation */ gnutls_assert (); _gnutls_free_datum (&encrypted); return GNUTLS_E_INTERNAL_ERROR; } ciphertext->data = gnutls_malloc (psize); if (ciphertext->data == NULL) { gnutls_assert (); _gnutls_free_datum (&encrypted); return GNUTLS_E_MEMORY_ERROR; } memcpy (&ciphertext->data[pad], encrypted.data, encrypted.size); for (i = 0; i < pad; i++) ciphertext->data[i] = 0; ciphertext->size = k; _gnutls_free_datum (&encrypted); return 0; }
/** * gnutls_openpgp_privkey_sign_hash: * @key: Holds the key * @hash: holds the data to be signed * @signature: will contain newly allocated signature * * This function will sign the given hash using the private key. You * should use gnutls_openpgp_privkey_set_preferred_key_id() before * calling this function to set the subkey to use. * * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a * negative error value. * * Deprecated: Use gnutls_privkey_sign_hash() instead. */ int gnutls_openpgp_privkey_sign_hash(gnutls_openpgp_privkey_t key, const gnutls_datum_t * hash, gnutls_datum_t * signature) { int result; gnutls_pk_params_st params; int pk_algorithm; uint8_t keyid[GNUTLS_OPENPGP_KEYID_SIZE]; char buf[2 * GNUTLS_OPENPGP_KEYID_SIZE + 1]; if (key == NULL) { gnutls_assert(); return GNUTLS_E_INVALID_REQUEST; } result = gnutls_openpgp_privkey_get_preferred_key_id(key, keyid); if (result == 0) { uint32_t kid[2]; int idx; KEYID_IMPORT(kid, keyid); _gnutls_hard_log("Signing using PGP key ID %s\n", _gnutls_bin2hex(keyid, GNUTLS_OPENPGP_KEYID_SIZE, buf, sizeof(buf), NULL)); idx = gnutls_openpgp_privkey_get_subkey_idx(key, keyid); pk_algorithm = gnutls_openpgp_privkey_get_subkey_pk_algorithm(key, idx, NULL); result = _gnutls_openpgp_privkey_get_mpis(key, kid, ¶ms); } else { _gnutls_hard_log("Signing using master PGP key\n"); pk_algorithm = gnutls_openpgp_privkey_get_pk_algorithm(key, NULL); result = _gnutls_openpgp_privkey_get_mpis(key, NULL, ¶ms); } if (result < 0) { gnutls_assert(); return result; } result = _gnutls_pk_sign(pk_algorithm, signature, hash, ¶ms); gnutls_pk_params_clear(¶ms); gnutls_pk_params_release(¶ms); if (result < 0) { gnutls_assert(); return result; } return 0; }
static int pct_test(gnutls_pk_algorithm_t algo, const gnutls_pk_params_st* params) { int ret; gnutls_datum_t sig = {NULL, 0}; const char const_data[20] = "onetwothreefourfive"; gnutls_datum_t ddata, tmp = {NULL,0}; char* gen_data = NULL; if (algo == GNUTLS_PK_DSA || algo == GNUTLS_PK_EC) { unsigned hash_len; _gnutls_dsa_q_to_hash(algo, params, &hash_len); gen_data = gnutls_malloc(hash_len); gnutls_rnd(GNUTLS_RND_NONCE, gen_data, hash_len); ddata.data = (void*)gen_data; ddata.size = hash_len; } else { ddata.data = (void*)const_data; ddata.size = sizeof(const_data); } switch (algo) { case GNUTLS_PK_RSA: ret = _gnutls_pk_encrypt(algo, &sig, &ddata, params); if (ret < 0) { ret = gnutls_assert_val(GNUTLS_E_PK_GENERATION_ERROR); goto cleanup; } if (ddata.size == sig.size && memcmp(ddata.data, sig.data, sig.size) == 0) { ret = gnutls_assert_val(GNUTLS_E_PK_GENERATION_ERROR); gnutls_assert(); goto cleanup; } ret = _gnutls_pk_decrypt(algo, &tmp, &sig, params); if (ret < 0) { ret = gnutls_assert_val(GNUTLS_E_PK_GENERATION_ERROR); gnutls_assert(); goto cleanup; } if (tmp.size != ddata.size || memcmp(tmp.data, ddata.data, tmp.size) != 0) { ret = gnutls_assert_val(GNUTLS_E_PK_GENERATION_ERROR); gnutls_assert(); goto cleanup; } free(sig.data); sig.data = NULL; /* Here we don't know the purpose of the key. Check both * signing and encryption. */ case GNUTLS_PK_EC: /* we only do keys for ECDSA */ case GNUTLS_PK_DSA: ret = _gnutls_pk_sign(algo, &sig, &ddata, params); if (ret < 0) { ret = gnutls_assert_val(GNUTLS_E_PK_GENERATION_ERROR); goto cleanup; } ret = _gnutls_pk_verify(algo, &ddata, &sig, params); if (ret < 0) { ret = gnutls_assert_val(GNUTLS_E_PK_GENERATION_ERROR); gnutls_assert(); goto cleanup; } break; default: ret = gnutls_assert_val(GNUTLS_E_UNKNOWN_PK_ALGORITHM); goto cleanup; } ret = 0; cleanup: if (ret == GNUTLS_E_PK_GENERATION_ERROR) { _gnutls_switch_lib_state(LIB_STATE_ERROR); } gnutls_free(gen_data); gnutls_free(sig.data); gnutls_free(tmp.data); return ret; }