Beispiel #1
0
/* Initializes the nonce level random generator.
 *
 * the @nonce_key must be provided.
 *
 * @init must be non zero on first initialization, and
 * zero on any subsequent reinitializations.
 */
static int nonce_rng_init(struct nonce_ctx_st *ctx,
			  uint8_t nonce_key[NONCE_KEY_SIZE],
			  unsigned nonce_key_size,
			  unsigned init)
{
	uint8_t iv[8];
	int ret;

	if (init == 0) {
		/* use the previous key to generate IV as well */
		memset(iv, 0, sizeof(iv)); /* to prevent valgrind from whinning */
		salsa20r12_crypt(&ctx->ctx, sizeof(iv), iv, iv);

		/* Add key continuity by XORing the new key with data generated
		 * from the old key */
		salsa20r12_crypt(&ctx->ctx, nonce_key_size, nonce_key, nonce_key);
	} else {
		ctx->forkid = _gnutls_get_forkid();

		/* when initializing read the IV from the system randomness source */
		ret = _rnd_get_system_entropy(iv, sizeof(iv));
		if (ret < 0)
			return gnutls_assert_val(ret);
	}

	salsa20_set_key(&ctx->ctx, nonce_key_size, nonce_key);
	salsa20_set_iv(&ctx->ctx, iv);

	zeroize_key(nonce_key, nonce_key_size);

	ctx->counter = 0;

	return 0;
}
Beispiel #2
0
/* Initializes the nonce level random generator.
 *
 * the @new_key must be provided.
 *
 * @init must be non zero on first initialization, and
 * zero on any subsequent reinitializations.
 */
static int single_prng_init(struct prng_ctx_st *ctx,
			    uint8_t new_key[PRNG_KEY_SIZE],
			    unsigned new_key_size,
			    unsigned init)
{
	uint8_t nonce[CHACHA_NONCE_SIZE];

	memset(nonce, 0, sizeof(nonce)); /* to prevent valgrind from whinning */

	if (init == 0) {
		/* use the previous key to generate IV as well */
		chacha_crypt(&ctx->ctx, sizeof(nonce), nonce, nonce);

		/* Add key continuity by XORing the new key with data generated
		 * from the old key */
		chacha_crypt(&ctx->ctx, new_key_size, new_key, new_key);
	} else {
		struct timespec now; /* current time */

		ctx->forkid = _gnutls_get_forkid();

		gettime(&now);
		memcpy(nonce, &now, MIN(sizeof(nonce), sizeof(now)));
		ctx->last_reseed = now.tv_sec;
	}

	chacha_set_key(&ctx->ctx, new_key);
	chacha_set_nonce(&ctx->ctx, nonce);

	zeroize_key(new_key, new_key_size);

	ctx->counter = 0;

	return 0;
}
Beispiel #3
0
static void _rngfips_deinit(void *_ctx)
{
	struct fips_ctx *ctx = _ctx;

	gnutls_mutex_deinit(&rnd_mutex);
	rnd_mutex = NULL;

	zeroize_key(ctx, sizeof(*ctx));
	free(ctx);
}
Beispiel #4
0
/* this function opens the tpasswd.conf file and reads the g and n
 * values. They are put in the entry.
 */
static int
pwd_read_conf(const char *pconf_file, SRP_PWD_ENTRY * entry, int idx)
{
	FILE *fd;
	char *line = NULL;
	size_t line_size = 0;
	unsigned i, len;
	char indexstr[10];
	int ret;

	snprintf(indexstr, sizeof(indexstr), "%u", (unsigned int) idx);

	fd = fopen(pconf_file, "r");
	if (fd == NULL) {
		gnutls_assert();
		return GNUTLS_E_FILE_ERROR;
	}

	len = strlen(indexstr);
	while (getline(&line, &line_size, fd) > 0) {
		/* move to first ':' */
		i = 0;
		while ((i < line_size) && (line[i] != ':')
                       && (line[i] != '\0')) {
			i++;
		}

		if (strncmp(indexstr, line, MAX(i, len)) == 0) {
			if ((idx =
			     parse_tpasswd_conf_values(entry,
						       line)) >= 0) {
				ret = 0;
				goto cleanup;
			} else {
				ret = GNUTLS_E_SRP_PWD_ERROR;
				goto cleanup;
			}
		}
	}
	ret = GNUTLS_E_SRP_PWD_ERROR;

cleanup:
	zeroize_key(line, line_size);
	free(line);
	fclose(fd);
	return ret;

}
Beispiel #5
0
static int drbg_init(struct drbg_aes_ctx *ctx)
{
	uint8_t buffer[DRBG_AES_SEED_SIZE];
	int ret;

	/* Get a key from the standard RNG or from the entropy source.  */
	ret = _rnd_get_system_entropy(buffer, sizeof(buffer));
	if (ret < 0)
		return gnutls_assert_val(ret);

	ret = drbg_aes_init(ctx, sizeof(buffer), buffer, PSTRING_SIZE, (void*)PSTRING);
	if (ret == 0)
		return gnutls_assert_val(GNUTLS_E_RANDOM_FAILED);

	zeroize_key(buffer, sizeof(buffer));

	return 0;
}
Beispiel #6
0
/* Returns the PSK key of the given user. 
 * If the user doesn't exist a random password is returned instead.
 */
int
_gnutls_psk_pwd_find_entry(gnutls_session_t session, char *username,
			   gnutls_datum_t * psk)
{
	gnutls_psk_server_credentials_t cred;
	FILE *fd;
	char *line = NULL;
	size_t line_size = 0;
	unsigned i, len;
	int ret;

	cred = (gnutls_psk_server_credentials_t)
	    _gnutls_get_cred(session, GNUTLS_CRD_PSK);
	if (cred == NULL) {
		gnutls_assert();
		return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
	}

	/* if the callback which sends the parameters is
	 * set, use it.
	 */
	if (cred->pwd_callback != NULL) {
		ret = cred->pwd_callback(session, username, psk);

		if (ret == 1) {	/* the user does not exist */
			ret = _randomize_psk(psk);
			if (ret < 0) {
				gnutls_assert();
				return ret;
			}
			return 0;
		}

		if (ret < 0) {
			gnutls_assert();
			return GNUTLS_E_SRP_PWD_ERROR;
		}

		return 0;
	}

	/* The callback was not set. Proceed.
	 */
	if (cred->password_file == NULL) {
		gnutls_assert();
		return GNUTLS_E_SRP_PWD_ERROR;
	}

	/* Open the selected password file.
	 */
	fd = fopen(cred->password_file, "r");
	if (fd == NULL) {
		gnutls_assert();
		return GNUTLS_E_SRP_PWD_ERROR;
	}

	len = strlen(username);
	while (getline(&line, &line_size, fd) > 0) {
		/* move to first ':' */
		i = 0;
		while ((i < line_size) && (line[i] != '\0')
		       && (line[i] != ':')) {
			i++;
		}

		if (strncmp(username, line, MAX(i, len)) == 0) {
			ret = pwd_put_values(psk, line);
			if (ret < 0) {
				gnutls_assert();
				ret = GNUTLS_E_SRP_PWD_ERROR;
				goto cleanup;
			}
			ret = 0;
			goto cleanup;
		}
	}

	/* user was not found. Fake him. 
	 */
	ret = _randomize_psk(psk);
	if (ret < 0) {
		goto cleanup;
	}

	ret = 0;
cleanup:
	if (fd != NULL)
		fclose(fd);
        
        zeroize_key(line, line_size);
	free(line);

	return ret;

}
/**
 * gnutls_x509_privkey_import_openssl:
 * @key: The structure to store the parsed key
 * @data: The DER or PEM encoded key.
 * @password: the password to decrypt the key (if it is encrypted).
 *
 * This function will convert the given PEM encrypted to 
 * the native gnutls_x509_privkey_t format. The
 * output will be stored in @key.  
 *
 * The @password should be in ASCII. If the password is not provided
 * or wrong then %GNUTLS_E_DECRYPTION_FAILED will be returned.
 *
 * If the Certificate is PEM encoded it should have a header of
 * "PRIVATE KEY" and the "DEK-Info" header. 
 *
 * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
 *   negative error value.
 **/
int
gnutls_x509_privkey_import_openssl(gnutls_x509_privkey_t key,
				   const gnutls_datum_t * data,
				   const char *password)
{
	gnutls_cipher_hd_t handle;
	gnutls_cipher_algorithm_t cipher = GNUTLS_CIPHER_UNKNOWN;
	gnutls_datum_t b64_data;
	gnutls_datum_t salt, enc_key;
	unsigned char *key_data;
	size_t key_data_size;
	const char *pem_header = (void *) data->data;
	const char *pem_header_start = (void *) data->data;
	ssize_t pem_header_size;
	int ret;
	unsigned int i, iv_size, l;

	pem_header_size = data->size;

	pem_header =
	    memmem(pem_header, pem_header_size, "PRIVATE KEY---", 14);
	if (pem_header == NULL) {
		gnutls_assert();
		return GNUTLS_E_PARSING_ERROR;
	}

	pem_header_size -= (ptrdiff_t) (pem_header - pem_header_start);

	pem_header = memmem(pem_header, pem_header_size, "DEK-Info: ", 10);
	if (pem_header == NULL) {
		gnutls_assert();
		return GNUTLS_E_PARSING_ERROR;
	}

	pem_header_size =
	    data->size - (ptrdiff_t) (pem_header - pem_header_start) - 10;
	pem_header += 10;

	for (i = 0; i < sizeof(pem_ciphers) / sizeof(pem_ciphers[0]); i++) {
		l = strlen(pem_ciphers[i].name);
		if (!strncmp(pem_header, pem_ciphers[i].name, l) &&
		    pem_header[l] == ',') {
			pem_header += l + 1;
			cipher = pem_ciphers[i].cipher;
			break;
		}
	}

	if (cipher == GNUTLS_CIPHER_UNKNOWN) {
		_gnutls_debug_log
		    ("Unsupported PEM encryption type: %.10s\n",
		     pem_header);
		gnutls_assert();
		return GNUTLS_E_INVALID_REQUEST;
	}

	iv_size = gnutls_cipher_get_iv_size(cipher);
	salt.size = iv_size;
	salt.data = gnutls_malloc(salt.size);
	if (!salt.data)
		return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);

	for (i = 0; i < salt.size * 2; i++) {
		unsigned char x;
		const char *c = &pem_header[i];

		if (*c >= '0' && *c <= '9')
			x = (*c) - '0';
		else if (*c >= 'A' && *c <= 'F')
			x = (*c) - 'A' + 10;
		else {
			gnutls_assert();
			/* Invalid salt in encrypted PEM file */
			ret = GNUTLS_E_INVALID_REQUEST;
			goto out_salt;
		}
		if (i & 1)
			salt.data[i / 2] |= x;
		else
			salt.data[i / 2] = x << 4;
	}

	pem_header += salt.size * 2;
	if (*pem_header != '\r' && *pem_header != '\n') {
		gnutls_assert();
		ret = GNUTLS_E_INVALID_REQUEST;
		goto out_salt;
	}
	while (*pem_header == '\n' || *pem_header == '\r')
		pem_header++;

	ret =
	    _gnutls_base64_decode((const void *) pem_header,
				  pem_header_size, &b64_data);
	if (ret < 0) {
		gnutls_assert();
		goto out_salt;
	}

	if (b64_data.size < 16) {
		/* Just to be sure our parsing is OK */
		gnutls_assert();
		ret = GNUTLS_E_PARSING_ERROR;
		goto out_b64;
	}

	ret = GNUTLS_E_MEMORY_ERROR;
	enc_key.size = gnutls_cipher_get_key_size(cipher);
	enc_key.data = gnutls_malloc(enc_key.size);
	if (!enc_key.data) {
		ret = gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
		goto out_b64;
	}

	key_data_size = b64_data.size;
	key_data = gnutls_malloc(key_data_size);
	if (!key_data) {
		ret = gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
		goto out_enc_key;
	}

	while (1) {
		memcpy(key_data, b64_data.data, key_data_size);

		ret = openssl_hash_password(password, &enc_key, &salt);
		if (ret < 0) {
			gnutls_assert();
			goto out;
		}

		ret = gnutls_cipher_init(&handle, cipher, &enc_key, &salt);
		if (ret < 0) {
			gnutls_assert();
			gnutls_cipher_deinit(handle);
			goto out;
		}

		ret =
		    gnutls_cipher_decrypt(handle, key_data, key_data_size);
		gnutls_cipher_deinit(handle);

		if (ret < 0) {
			gnutls_assert();
			goto out;
		}

		/* We have to strip any padding to accept it.
		   So a bit more ASN.1 parsing for us. */
		if (key_data[0] == 0x30) {
			gnutls_datum_t key_datum;
			unsigned int blocksize =
			    gnutls_cipher_get_block_size(cipher);
			unsigned int keylen = key_data[1];
			unsigned int ofs = 2;

			if (keylen & 0x80) {
				int lenlen = keylen & 0x7f;
				keylen = 0;

				if (lenlen > 3) {
					gnutls_assert();
					goto fail;
				}

				while (lenlen) {
					keylen <<= 8;
					keylen |= key_data[ofs++];
					lenlen--;
				}
			}
			keylen += ofs;

			/* If there appears to be more padding than required, fail */
			if (key_data_size - keylen > blocksize) {
				gnutls_assert();
				goto fail;
			}

			/* If the padding bytes aren't all equal to the amount of padding, fail */
			ofs = keylen;
			while (ofs < key_data_size) {
				if (key_data[ofs] !=
				    key_data_size - keylen) {
					gnutls_assert();
					goto fail;
				}
				ofs++;
			}

			key_datum.data = key_data;
			key_datum.size = keylen;
			ret =
			    gnutls_x509_privkey_import(key, &key_datum,
						       GNUTLS_X509_FMT_DER);
			if (ret == 0)
				goto out;
		}
	      fail:
		ret = GNUTLS_E_DECRYPTION_FAILED;
		goto out;
	}
      out:
	zeroize_key(key_data, key_data_size);
	gnutls_free(key_data);
      out_enc_key:
	_gnutls_free_key_datum(&enc_key);
      out_b64:
	gnutls_free(b64_data.data);
      out_salt:
	gnutls_free(salt.data);
	return ret;
}
Beispiel #8
0
static void wrap_nettle_mpi_clear(bigint_t a)
{
	zeroize_key(TOMPZ(a)[0]._mp_d,
	       TOMPZ(a)[0]._mp_alloc * sizeof(mp_limb_t));
}
Beispiel #9
0
static void 
ecc_point_zclear (struct ecc_point *p)
{
        zeroize_key(p->p, ecc_size_a(p->ecc)*sizeof(mp_limb_t));
        ecc_point_clear(p);
}
Beispiel #10
0
static void
ecc_scalar_zclear (struct ecc_scalar *s)
{
        zeroize_key(s->p, ecc_size(s->ecc)*sizeof(mp_limb_t));
        ecc_scalar_clear(s);
}
Beispiel #11
0
int
_gnutls_srp_pwd_read_entry(gnutls_session_t state, char *username,
			   SRP_PWD_ENTRY ** _entry)
{
	gnutls_srp_server_credentials_t cred;
	FILE *fd = NULL;
	char *line = NULL;
	size_t line_size = 0;
	unsigned i, len;
	int ret;
	int idx;
	SRP_PWD_ENTRY *entry = NULL;

	*_entry = gnutls_calloc(1, sizeof(SRP_PWD_ENTRY));
	if (*_entry == NULL) {
		gnutls_assert();
		return GNUTLS_E_MEMORY_ERROR;
	}
	entry = *_entry;

	cred = (gnutls_srp_server_credentials_t)
	    _gnutls_get_cred(state, GNUTLS_CRD_SRP);
	if (cred == NULL) {
		gnutls_assert();
		ret = GNUTLS_E_INSUFFICIENT_CREDENTIALS;
		goto cleanup;
	}

	/* if the callback which sends the parameters is
	 * set, use it.
	 */
	if (cred->pwd_callback != NULL) {
		ret = cred->pwd_callback(state, username, &entry->salt,
					 &entry->v, &entry->g, &entry->n);

		if (ret == 1) {	/* the user does not exist */
			if (entry->g.size != 0 && entry->n.size != 0) {
				ret = _randomize_pwd_entry(entry, cred, username);
				if (ret < 0) {
					gnutls_assert();
					goto cleanup;
				}
				return 0;
			} else {
				gnutls_assert();
				ret = -1;	/* error in the callback */
			}
		}

		if (ret < 0) {
			gnutls_assert();
			ret = GNUTLS_E_SRP_PWD_ERROR;
			goto cleanup;
		}

		return 0;
	}

	/* The callback was not set. Proceed.
	 */

	if (cred->password_file == NULL) {
		gnutls_assert();
		ret = GNUTLS_E_SRP_PWD_ERROR;
		goto cleanup;
	}

	/* Open the selected password file.
	 */
	fd = fopen(cred->password_file, "r");
	if (fd == NULL) {
		gnutls_assert();
		ret = GNUTLS_E_SRP_PWD_ERROR;
		goto cleanup;
	}

	len = strlen(username);
	while (getline(&line, &line_size, fd) > 0) {
		/* move to first ':' */
		i = 0;
		while ((i < line_size) && (line[i] != '\0')
		       && (line[i] != ':')) {
			i++;
		}

		if (strncmp(username, line, MAX(i, len)) == 0) {
			if ((idx = parse_tpasswd_values(entry, line)) >= 0) {
				/* Keep the last index in memory, so we can retrieve fake parameters (g,n)
				 * when the user does not exist.
				 */
				if (pwd_read_conf
				    (cred->password_conf_file, entry,
				     idx) == 0) {
					ret = 0;
					goto found;
				} else {
					gnutls_assert();
					ret = GNUTLS_E_SRP_PWD_ERROR;
					goto cleanup;
				}
			} else {
				gnutls_assert();
				ret = GNUTLS_E_SRP_PWD_ERROR;
				goto cleanup;
			}
		}
	}

	/* user was not found. Fake him. Actually read the g,n values from
	 * the last index found and randomize the entry.
	 */
	if (pwd_read_conf(cred->password_conf_file, entry, 1) == 0) {
		ret = _randomize_pwd_entry(entry, cred, username);
		if (ret < 0) {
			gnutls_assert();
			goto cleanup;
		}

		ret = 0;
		goto found;
	}

	ret = GNUTLS_E_SRP_PWD_ERROR;

cleanup:
	gnutls_assert();
	_gnutls_srp_entry_free(entry);

found:
	zeroize_key(line, line_size);
	free(line);
	if (fd)
		fclose(fd);
	return ret;
}