Merge changes from topic "jc/rsa-pkcs" into integration

* changes:
  Remove RSA PKCS#1 v1.5 support from cert_tool
  Add documentation for new KEY_SIZE option
  Add cert_create tool support for RSA key sizes
  Support larger RSA key sizes when using MBEDTLS
diff --git a/Makefile b/Makefile
index ecff944..32918c3 100644
--- a/Makefile
+++ b/Makefile
@@ -695,6 +695,10 @@
 $(eval $(call assert_numeric,ARM_ARCH_MINOR))
 $(eval $(call assert_numeric,BRANCH_PROTECTION))
 
+ifdef KEY_SIZE
+        $(eval $(call assert_numeric,KEY_SIZE))
+endif
+
 ifeq ($(filter $(SANITIZE_UB), on off trap),)
         $(error "Invalid value for SANITIZE_UB: can be one of on, off, trap")
 endif
diff --git a/docs/design/auth-framework.rst b/docs/design/auth-framework.rst
index da958b7..7de8ee1 100644
--- a/docs/design/auth-framework.rst
+++ b/docs/design/auth-framework.rst
@@ -704,7 +704,7 @@
 
 In the ``tbbr_cot.c`` file, a set of buffers are allocated to store the parameters
 extracted from the certificates. In the case of the TBBR CoT, these parameters
-are hashes and public keys. In DER format, an RSA-2048 public key requires 294
+are hashes and public keys. In DER format, an RSA-4096 public key requires 550
 bytes, and a hash requires 51 bytes. Depending on the CoT and the authentication
 process, some of the buffers may be reused at different stages during the boot.
 
@@ -946,12 +946,16 @@
     int verify_hash(void *data_ptr, unsigned int data_len,
                     void *digest_info_ptr, unsigned int digest_info_len);
 
-The mbedTLS library algorithm support is configured by the
-``TF_MBEDTLS_KEY_ALG`` variable which can take in 3 values: `rsa`, `ecdsa` or
-`rsa+ecdsa`. This variable allows the Makefile to include the corresponding
-sources in the build for the various algorithms. Setting the variable to
-`rsa+ecdsa` enables support for both rsa and ecdsa algorithms in the mbedTLS
-library.
+The mbedTLS library algorithm support is configured by both the
+``TF_MBEDTLS_KEY_ALG`` and ``TF_MBEDTLS_KEY_SIZE`` variables.
+
+-  ``TF_MBEDTLS_KEY_ALG`` can take in 3 values: `rsa`, `ecdsa` or `rsa+ecdsa`.
+   This variable allows the Makefile to include the corresponding sources in
+   the build for the various algorithms. Setting the variable to `rsa+ecdsa`
+   enables support for both rsa and ecdsa algorithms in the mbedTLS library.
+
+-  ``TF_MBEDTLS_KEY_SIZE`` sets the supported RSA key size for TFA. Valid values
+   include 1024, 2048, 3072 and 4096.
 
 .. note::
    If code size is a concern, the build option ``MBEDTLS_SHA256_SMALLER`` can
diff --git a/docs/getting_started/user-guide.rst b/docs/getting_started/user-guide.rst
index 3828d0b..015de9a 100644
--- a/docs/getting_started/user-guide.rst
+++ b/docs/getting_started/user-guide.rst
@@ -594,10 +594,20 @@
 
 -  ``KEY_ALG``: This build flag enables the user to select the algorithm to be
    used for generating the PKCS keys and subsequent signing of the certificate.
-   It accepts 3 values: ``rsa``, ``rsa_1_5`` and ``ecdsa``. The option
-   ``rsa_1_5`` is the legacy PKCS#1 RSA 1.5 algorithm which is not TBBR
-   compliant and is retained only for compatibility. The default value of this
-   flag is ``rsa`` which is the TBBR compliant PKCS#1 RSA 2.1 scheme.
+   It accepts 2 values: ``rsa`` and ``ecdsa``. The default value of this flag
+   is ``rsa`` which is the TBBR compliant PKCS#1 RSA 2.1 scheme.
+
+-  ``KEY_SIZE``: This build flag enables the user to select the key size for
+   the algorithm specified by ``KEY_ALG``. The valid values for ``KEY_SIZE``
+   depend on the chosen algorithm.
+
+   +-----------+------------------------------------+
+   |  KEY_ALG  |        Possible key sizes          |
+   +===========+====================================+
+   |    rsa    |  1024, 2048 (default), 3072, 4096  |
+   +-----------+------------------------------------+
+   |   ecdsa   |            unavailable             |
+   +-----------+------------------------------------+
 
 -  ``HASH_ALG``: This build flag enables the user to select the secure hash
    algorithm. It accepts 3 values: ``sha256``, ``sha384`` and ``sha512``.
diff --git a/drivers/auth/mbedtls/mbedtls_common.mk b/drivers/auth/mbedtls/mbedtls_common.mk
index 63e65bd..4b83015 100644
--- a/drivers/auth/mbedtls/mbedtls_common.mk
+++ b/drivers/auth/mbedtls/mbedtls_common.mk
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -48,9 +48,9 @@
 					)
 
 # The platform may define the variable 'TF_MBEDTLS_KEY_ALG' to select the key
-# algorithm to use. If the variable is not defined, select it based on algorithm
-# used for key generation `KEY_ALG`. If `KEY_ALG` is not defined or is
-# defined to `rsa`/`rsa_1_5`, then set the variable to `rsa`.
+# algorithm to use. If the variable is not defined, select it based on
+# algorithm used for key generation `KEY_ALG`. If `KEY_ALG` is not defined,
+# then it is set to `rsa`.
 ifeq (${TF_MBEDTLS_KEY_ALG},)
     ifeq (${KEY_ALG}, ecdsa)
         TF_MBEDTLS_KEY_ALG		:=	ecdsa
@@ -59,6 +59,16 @@
     endif
 endif
 
+ifeq (${TF_MBEDTLS_KEY_SIZE},)
+    ifneq ($(findstring rsa,${TF_MBEDTLS_KEY_ALG}),)
+	ifeq (${KEY_SIZE},)
+            TF_MBEDTLS_KEY_SIZE		:=	2048
+	else
+            TF_MBEDTLS_KEY_SIZE		:=	${KEY_SIZE}
+	endif
+    endif
+endif
+
 ifeq (${HASH_ALG}, sha384)
     TF_MBEDTLS_HASH_ALG_ID	:=	TF_MBEDTLS_SHA384
 else ifeq (${HASH_ALG}, sha512)
@@ -79,6 +89,7 @@
 
 # Needs to be set to drive mbed TLS configuration correctly
 $(eval $(call add_define,TF_MBEDTLS_KEY_ALG_ID))
+$(eval $(call add_define,TF_MBEDTLS_KEY_SIZE))
 $(eval $(call add_define,TF_MBEDTLS_HASH_ALG_ID))
 
 
diff --git a/drivers/auth/tbbr/tbbr_cot.c b/drivers/auth/tbbr/tbbr_cot.c
index da3631b..6dd4ae2 100644
--- a/drivers/auth/tbbr/tbbr_cot.c
+++ b/drivers/auth/tbbr/tbbr_cot.c
@@ -7,6 +7,7 @@
 #include <stddef.h>
 
 #include <platform_def.h>
+#include <drivers/auth/mbedtls/mbedtls_config.h>
 
 #include <drivers/auth/auth_mod.h>
 #if USE_TBBR_DEFS
@@ -19,7 +20,22 @@
 /*
  * Maximum key and hash sizes (in DER format)
  */
+#if TF_MBEDTLS_USE_RSA
+#if TF_MBEDTLS_KEY_SIZE == 1024
+#define PK_DER_LEN			162
+#elif TF_MBEDTLS_KEY_SIZE == 2048
 #define PK_DER_LEN			294
+#elif TF_MBEDTLS_KEY_SIZE == 3072
+#define PK_DER_LEN			422
+#elif TF_MBEDTLS_KEY_SIZE == 4096
+#define PK_DER_LEN			550
+#else
+#error "Invalid value for TF_MBEDTLS_KEY_SIZE"
+#endif
+#else
+#define PK_DER_LEN			294
+#endif
+
 #define HASH_DER_LEN			83
 
 /*
diff --git a/include/drivers/auth/mbedtls/mbedtls_config.h b/include/drivers/auth/mbedtls/mbedtls_config.h
index f7248f9..6e179bb 100644
--- a/include/drivers/auth/mbedtls/mbedtls_config.h
+++ b/include/drivers/auth/mbedtls/mbedtls_config.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -13,6 +13,11 @@
 #define TF_MBEDTLS_ECDSA		2
 #define TF_MBEDTLS_RSA_AND_ECDSA	3
 
+#define TF_MBEDTLS_USE_RSA (TF_MBEDTLS_KEY_ALG_ID == TF_MBEDTLS_RSA \
+		|| TF_MBEDTLS_KEY_ALG_ID == TF_MBEDTLS_RSA_AND_ECDSA)
+#define TF_MBEDTLS_USE_ECDSA (TF_MBEDTLS_KEY_ALG_ID == TF_MBEDTLS_ECDSA \
+		|| TF_MBEDTLS_KEY_ALG_ID == TF_MBEDTLS_RSA_AND_ECDSA)
+
 /*
  * Hash algorithms currently supported on mbed TLS libraries
  */
@@ -54,19 +59,14 @@
 
 #define MBEDTLS_PLATFORM_C
 
-#if (TF_MBEDTLS_KEY_ALG_ID == TF_MBEDTLS_ECDSA)
+#if TF_MBEDTLS_USE_ECDSA
 #define MBEDTLS_ECDSA_C
 #define MBEDTLS_ECP_C
 #define MBEDTLS_ECP_DP_SECP256R1_ENABLED
-#elif (TF_MBEDTLS_KEY_ALG_ID == TF_MBEDTLS_RSA)
+#endif
+#if TF_MBEDTLS_USE_RSA
 #define MBEDTLS_RSA_C
 #define MBEDTLS_X509_RSASSA_PSS_SUPPORT
-#elif (TF_MBEDTLS_KEY_ALG_ID == TF_MBEDTLS_RSA_AND_ECDSA)
-#define MBEDTLS_RSA_C
-#define MBEDTLS_X509_RSASSA_PSS_SUPPORT
-#define MBEDTLS_ECDSA_C
-#define MBEDTLS_ECP_C
-#define MBEDTLS_ECP_DP_SECP256R1_ENABLED
 #endif
 
 #define MBEDTLS_SHA256_C
@@ -80,11 +80,20 @@
 #define MBEDTLS_X509_CRT_PARSE_C
 
 /* MPI / BIGNUM options */
-#define MBEDTLS_MPI_WINDOW_SIZE              2
-#define MBEDTLS_MPI_MAX_SIZE               256
+#define MBEDTLS_MPI_WINDOW_SIZE			2
+
+#if TF_MBEDTLS_USE_RSA
+#if TF_MBEDTLS_KEY_SIZE <= 2048
+#define MBEDTLS_MPI_MAX_SIZE			256
+#else
+#define MBEDTLS_MPI_MAX_SIZE			512
+#endif
+#else
+#define MBEDTLS_MPI_MAX_SIZE			256
+#endif
 
 /* Memory buffer allocator options */
-#define MBEDTLS_MEMORY_ALIGN_MULTIPLE        8
+#define MBEDTLS_MEMORY_ALIGN_MULTIPLE		8
 
 #ifndef __ASSEMBLER__
 /* System headers required to build mbed TLS with the current configuration */
@@ -95,13 +104,17 @@
 /*
  * Determine Mbed TLS heap size
  * 13312 = 13*1024
- * 7168 = 7*1024
+ * 11264 = 11*1024
+ * 7168  = 7*1024
  */
-#if (TF_MBEDTLS_KEY_ALG_ID == TF_MBEDTLS_ECDSA) \
-	|| (TF_MBEDTLS_KEY_ALG_ID == TF_MBEDTLS_RSA_AND_ECDSA)
+#if TF_MBEDTLS_USE_ECDSA
 #define TF_MBEDTLS_HEAP_SIZE		U(13312)
-#elif (TF_MBEDTLS_KEY_ALG_ID == TF_MBEDTLS_RSA)
+#elif TF_MBEDTLS_USE_RSA
+#if TF_MBEDTLS_KEY_SIZE <= 2048
 #define TF_MBEDTLS_HEAP_SIZE		U(7168)
+#else
+#define TF_MBEDTLS_HEAP_SIZE		U(11264)
+#endif
 #endif
 
 #endif /* MBEDTLS_CONFIG_H */
diff --git a/make_helpers/tbbr/tbbr_tools.mk b/make_helpers/tbbr/tbbr_tools.mk
index afc007a..9c47cc7 100644
--- a/make_helpers/tbbr/tbbr_tools.mk
+++ b/make_helpers/tbbr/tbbr_tools.mk
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -21,6 +21,7 @@
 # Build options added by this file:
 #
 #   KEY_ALG
+#   KEY_SIZE
 #   ROT_KEY
 #   TRUSTED_WORLD_KEY
 #   NON_TRUSTED_WORLD_KEY
@@ -52,6 +53,7 @@
 # packed in the FIP). Developers can use their own keys by specifying the proper
 # build option in the command line when building the Trusted Firmware
 $(if ${KEY_ALG},$(eval $(call CERT_ADD_CMD_OPT,${KEY_ALG},--key-alg)))
+$(if ${KEY_SIZE},$(eval $(call CERT_ADD_CMD_OPT,${KEY_SIZE},--key-size)))
 $(if ${HASH_ALG},$(eval $(call CERT_ADD_CMD_OPT,${HASH_ALG},--hash-alg)))
 $(if ${ROT_KEY},$(eval $(call CERT_ADD_CMD_OPT,${ROT_KEY},--rot-key)))
 $(if ${ROT_KEY},$(eval $(call CERT_ADD_CMD_OPT,${ROT_KEY},--rot-key,FWU_)))
diff --git a/tools/cert_create/include/cert.h b/tools/cert_create/include/cert.h
index 39b45b5..6db9b57 100644
--- a/tools/cert_create/include/cert.h
+++ b/tools/cert_create/include/cert.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -49,7 +49,6 @@
 cert_t *cert_get_by_opt(const char *opt);
 int cert_add_ext(X509 *issuer, X509 *subject, int nid, char *value);
 int cert_new(
-	int key_alg,
 	int md_alg,
 	cert_t *cert,
 	int days,
diff --git a/tools/cert_create/include/key.h b/tools/cert_create/include/key.h
index 310a77f..d96d983 100644
--- a/tools/cert_create/include/key.h
+++ b/tools/cert_create/include/key.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -9,8 +9,6 @@
 
 #include <openssl/ossl_typ.h>
 
-#define RSA_KEY_BITS		2048
-
 /* Error codes */
 enum {
 	KEY_ERR_NONE,
@@ -23,13 +21,15 @@
 /* Supported key algorithms */
 enum {
 	KEY_ALG_RSA,		/* RSA PSS as defined by PKCS#1 v2.1 (default) */
-	KEY_ALG_RSA_1_5,	/* RSA as defined by PKCS#1 v1.5 */
 #ifndef OPENSSL_NO_EC
 	KEY_ALG_ECDSA,
 #endif /* OPENSSL_NO_EC */
 	KEY_ALG_MAX_NUM
 };
 
+/* Maximum number of valid key sizes per algorithm */
+#define KEY_SIZE_MAX_NUM	4
+
 /* Supported hash algorithms */
 enum{
 	HASH_ALG_SHA256,
@@ -37,6 +37,15 @@
 	HASH_ALG_SHA512,
 };
 
+/* Supported key sizes */
+/* NOTE: the first item in each array is the default key size */
+static const unsigned int KEY_SIZES[KEY_ALG_MAX_NUM][KEY_SIZE_MAX_NUM] = {
+	{ 2048, 1024, 3072, 4096 },	/* KEY_ALG_RSA */
+#ifndef OPENSSL_NO_EC
+	{}				/* KEY_ALG_ECDSA */
+#endif /* OPENSSL_NO_EC */
+};
+
 /*
  * This structure contains the relevant information to create the keys
  * required to sign the certificates.
@@ -58,7 +67,7 @@
 int key_init(void);
 key_t *key_get_by_opt(const char *opt);
 int key_new(key_t *key);
-int key_create(key_t *key, int type);
+int key_create(key_t *key, int type, int key_bits);
 int key_load(key_t *key, unsigned int *err_code);
 int key_store(key_t *key);
 
diff --git a/tools/cert_create/src/cert.c b/tools/cert_create/src/cert.c
index 8e8aee6..c68a265 100644
--- a/tools/cert_create/src/cert.c
+++ b/tools/cert_create/src/cert.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  */
@@ -93,7 +93,6 @@
 }
 
 int cert_new(
-	int key_alg,
 	int md_alg,
 	cert_t *cert,
 	int days,
@@ -143,10 +142,10 @@
 	}
 
 	/*
-	 * Set additional parameters if algorithm is RSA PSS. This is not
-	 * required for RSA 1.5 or ECDSA.
+	 * Set additional parameters if issuing public key algorithm is RSA.
+	 * This is not required for ECDSA.
 	 */
-	if (key_alg == KEY_ALG_RSA) {
+	if (EVP_PKEY_base_id(ikey) == EVP_PKEY_RSA) {
 		if (!EVP_PKEY_CTX_set_rsa_padding(pKeyCtx, RSA_PKCS1_PSS_PADDING)) {
 			ERR_print_errors_fp(stdout);
 			goto END;
diff --git a/tools/cert_create/src/key.c b/tools/cert_create/src/key.c
index fece770..0f80cce 100644
--- a/tools/cert_create/src/key.c
+++ b/tools/cert_create/src/key.c
@@ -41,7 +41,7 @@
 	return 1;
 }
 
-static int key_create_rsa(key_t *key)
+static int key_create_rsa(key_t *key, int key_bits)
 {
 	BIGNUM *e;
 	RSA *rsa = NULL;
@@ -63,7 +63,7 @@
 		goto err;
 	}
 
-	if (!RSA_generate_key_ex(rsa, RSA_KEY_BITS, e, NULL)) {
+	if (!RSA_generate_key_ex(rsa, key_bits, e, NULL)) {
 		printf("Cannot generate RSA key\n");
 		goto err;
 	}
@@ -82,7 +82,7 @@
 }
 
 #ifndef OPENSSL_NO_EC
-static int key_create_ecdsa(key_t *key)
+static int key_create_ecdsa(key_t *key, int key_bits)
 {
 	EC_KEY *ec;
 
@@ -109,16 +109,15 @@
 }
 #endif /* OPENSSL_NO_EC */
 
-typedef int (*key_create_fn_t)(key_t *key);
+typedef int (*key_create_fn_t)(key_t *key, int key_bits);
 static const key_create_fn_t key_create_fn[KEY_ALG_MAX_NUM] = {
 	key_create_rsa, 	/* KEY_ALG_RSA */
-	key_create_rsa, 	/* KEY_ALG_RSA_1_5 */
 #ifndef OPENSSL_NO_EC
 	key_create_ecdsa, 	/* KEY_ALG_ECDSA */
 #endif /* OPENSSL_NO_EC */
 };
 
-int key_create(key_t *key, int type)
+int key_create(key_t *key, int type, int key_bits)
 {
 	if (type >= KEY_ALG_MAX_NUM) {
 		printf("Invalid key type\n");
@@ -126,7 +125,7 @@
 	}
 
 	if (key_create_fn[type]) {
-		return key_create_fn[type](key);
+		return key_create_fn[type](key, key_bits);
 	}
 
 	return 0;
diff --git a/tools/cert_create/src/main.c b/tools/cert_create/src/main.c
index 0f588cc..0cbd219 100644
--- a/tools/cert_create/src/main.c
+++ b/tools/cert_create/src/main.c
@@ -10,6 +10,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <stdbool.h>
 
 #include <openssl/conf.h>
 #include <openssl/engine.h>
@@ -69,6 +70,7 @@
 /* Global options */
 static int key_alg;
 static int hash_alg;
+static int key_size;
 static int new_keys;
 static int save_keys;
 static int print_cert;
@@ -90,7 +92,6 @@
 
 static const char *key_algs_str[] = {
 	[KEY_ALG_RSA] = "rsa",
-	[KEY_ALG_RSA_1_5] = "rsa_1_5",
 #ifndef OPENSSL_NO_EC
 	[KEY_ALG_ECDSA] = "ecdsa"
 #endif /* OPENSSL_NO_EC */
@@ -155,6 +156,18 @@
 	return -1;
 }
 
+static int get_key_size(const char *key_size_str)
+{
+	char *end;
+	long key_size;
+
+	key_size = strtol(key_size_str, &end, 10);
+	if (*end != '\0')
+		return -1;
+
+	return key_size;
+}
+
 static int get_hash_alg(const char *hash_alg_str)
 {
 	int i;
@@ -174,6 +187,7 @@
 	ext_t *ext;
 	key_t *key;
 	int i, j;
+	bool valid_size;
 
 	/* Only save new keys */
 	if (save_keys && !new_keys) {
@@ -181,6 +195,26 @@
 		exit(1);
 	}
 
+	/* Validate key-size */
+	valid_size = false;
+	for (i = 0; i < KEY_SIZE_MAX_NUM; i++) {
+		if (key_size == KEY_SIZES[key_alg][i]) {
+			valid_size = true;
+			break;
+		}
+	}
+	if (!valid_size) {
+		ERROR("'%d' is not a valid key size for '%s'\n",
+				key_size, key_algs_str[key_alg]);
+		NOTICE("Valid sizes are: ");
+		for (i = 0; i < KEY_SIZE_MAX_NUM &&
+				KEY_SIZES[key_alg][i] != 0; i++) {
+			printf("%d ", KEY_SIZES[key_alg][i]);
+		}
+		printf("\n");
+		exit(1);
+	}
+
 	/* Check that all required options have been specified in the
 	 * command line */
 	for (i = 0; i < num_certs; i++) {
@@ -242,8 +276,11 @@
 	},
 	{
 		{ "key-alg", required_argument, NULL, 'a' },
-		"Key algorithm: 'rsa' (default) - RSAPSS scheme as per \
-PKCS#1 v2.1, 'rsa_1_5' - RSA PKCS#1 v1.5, 'ecdsa'"
+		"Key algorithm: 'rsa' (default)- RSAPSS scheme as per PKCS#1 v2.1, 'ecdsa'"
+	},
+	{
+		{ "key-size", required_argument, NULL, 'b' },
+		"Key size (for supported algorithms)."
 	},
 	{
 		{ "hash-alg", required_argument, NULL, 's' },
@@ -286,6 +323,7 @@
 	/* Set default options */
 	key_alg = KEY_ALG_RSA;
 	hash_alg = HASH_ALG_SHA256;
+	key_size = -1;
 
 	/* Add common command line options */
 	for (i = 0; i < NUM_ELEM(common_cmd_opt); i++) {
@@ -315,7 +353,7 @@
 
 	while (1) {
 		/* getopt_long stores the option index here. */
-		c = getopt_long(argc, argv, "a:hknps:", cmd_opt, &opt_idx);
+		c = getopt_long(argc, argv, "a:b:hknps:", cmd_opt, &opt_idx);
 
 		/* Detect the end of the options. */
 		if (c == -1) {
@@ -330,6 +368,13 @@
 				exit(1);
 			}
 			break;
+		case 'b':
+			key_size = get_key_size(optarg);
+			if (key_size <= 0) {
+				ERROR("Invalid key size '%s'\n", optarg);
+				exit(1);
+			}
+			break;
 		case 'h':
 			print_help(argv[0], cmd_opt);
 			exit(0);
@@ -371,6 +416,11 @@
 		}
 	}
 
+	/* Select a reasonable default key-size */
+	if (key_size == -1) {
+		key_size = KEY_SIZES[key_alg][0];
+	}
+
 	/* Check command line arguments */
 	check_cmd_params();
 
@@ -413,7 +463,7 @@
 		if (new_keys) {
 			/* Try to create a new key */
 			NOTICE("Creating new key for '%s'\n", keys[i].desc);
-			if (!key_create(&keys[i], key_alg)) {
+			if (!key_create(&keys[i], key_alg, key_size)) {
 				ERROR("Error creating key '%s'\n", keys[i].desc);
 				exit(1);
 			}
@@ -493,7 +543,7 @@
 		}
 
 		/* Create certificate. Signed with corresponding key */
-		if (cert->fn && !cert_new(key_alg, hash_alg, cert, VAL_DAYS, 0, sk)) {
+		if (cert->fn && !cert_new(hash_alg, cert, VAL_DAYS, 0, sk)) {
 			ERROR("Cannot create %s\n", cert->cn);
 			exit(1);
 		}