summaryrefslogtreecommitdiffstats
path: root/crypto/drbg.c
diff options
context:
space:
mode:
authorStephan Mueller <smueller@chronox.de>2015-05-25 09:09:14 -0400
committerHerbert Xu <herbert@gondor.apana.org.au>2015-05-27 05:51:53 -0400
commit3d6a5f75d1340539dcdcec4609761fa4b836a1f2 (patch)
treed19d3ccb4f4875c20dde086b8d7abe75b807a159 /crypto/drbg.c
parent16b369a91d0dd80be214b7f7801fbc51875454cc (diff)
crypto: drbg - prepare for async seeding
In order to prepare for the addition of the asynchronous seeding call, the invocation of seeding the DRBG is moved out into a helper function. In addition, a block of memory is allocated during initialization time that will be used as a scratchpad for obtaining entropy. That scratchpad is used for the initial seeding operation as well as by the asynchronous seeding call. The memory must be zeroized every time the DRBG seeding call succeeds to avoid entropy data lingering in memory. CC: Andreas Steffen <andreas.steffen@strongswan.org> CC: Theodore Ts'o <tytso@mit.edu> CC: Sandy Harris <sandyinchina@gmail.com> Signed-off-by: Stephan Mueller <smueller@chronox.de> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Diffstat (limited to 'crypto/drbg.c')
-rw-r--r--crypto/drbg.c81
1 files changed, 54 insertions, 27 deletions
diff --git a/crypto/drbg.c b/crypto/drbg.c
index 23d444ed3176..36dfece45e88 100644
--- a/crypto/drbg.c
+++ b/crypto/drbg.c
@@ -1041,6 +1041,21 @@ static struct drbg_state_ops drbg_hash_ops = {
1041 * Functions common for DRBG implementations 1041 * Functions common for DRBG implementations
1042 ******************************************************************/ 1042 ******************************************************************/
1043 1043
1044static inline int __drbg_seed(struct drbg_state *drbg, struct list_head *seed,
1045 int reseed)
1046{
1047 int ret = drbg->d_ops->update(drbg, seed, reseed);
1048
1049 if (ret)
1050 return ret;
1051
1052 drbg->seeded = true;
1053 /* 10.1.1.2 / 10.1.1.3 step 5 */
1054 drbg->reseed_ctr = 1;
1055
1056 return ret;
1057}
1058
1044/* 1059/*
1045 * Seeding or reseeding of the DRBG 1060 * Seeding or reseeding of the DRBG
1046 * 1061 *
@@ -1056,8 +1071,6 @@ static int drbg_seed(struct drbg_state *drbg, struct drbg_string *pers,
1056 bool reseed) 1071 bool reseed)
1057{ 1072{
1058 int ret = 0; 1073 int ret = 0;
1059 unsigned char *entropy = NULL;
1060 size_t entropylen = 0;
1061 struct drbg_string data1; 1074 struct drbg_string data1;
1062 LIST_HEAD(seedlist); 1075 LIST_HEAD(seedlist);
1063 1076
@@ -1073,26 +1086,10 @@ static int drbg_seed(struct drbg_state *drbg, struct drbg_string *pers,
1073 drbg->test_data.len); 1086 drbg->test_data.len);
1074 pr_devel("DRBG: using test entropy\n"); 1087 pr_devel("DRBG: using test entropy\n");
1075 } else { 1088 } else {
1076 /*
1077 * Gather entropy equal to the security strength of the DRBG.
1078 * With a derivation function, a nonce is required in addition
1079 * to the entropy. A nonce must be at least 1/2 of the security
1080 * strength of the DRBG in size. Thus, entropy * nonce is 3/2
1081 * of the strength. The consideration of a nonce is only
1082 * applicable during initial seeding.
1083 */
1084 entropylen = drbg_sec_strength(drbg->core->flags);
1085 if (!entropylen)
1086 return -EFAULT;
1087 if (!reseed)
1088 entropylen = ((entropylen + 1) / 2) * 3;
1089 pr_devel("DRBG: (re)seeding with %zu bytes of entropy\n", 1089 pr_devel("DRBG: (re)seeding with %zu bytes of entropy\n",
1090 entropylen); 1090 drbg->seed_buf_len);
1091 entropy = kzalloc(entropylen, GFP_KERNEL); 1091 get_random_bytes(drbg->seed_buf, drbg->seed_buf_len);
1092 if (!entropy) 1092 drbg_string_fill(&data1, drbg->seed_buf, drbg->seed_buf_len);
1093 return -ENOMEM;
1094 get_random_bytes(entropy, entropylen);
1095 drbg_string_fill(&data1, entropy, entropylen);
1096 } 1093 }
1097 list_add_tail(&data1.list, &seedlist); 1094 list_add_tail(&data1.list, &seedlist);
1098 1095
@@ -1111,16 +1108,24 @@ static int drbg_seed(struct drbg_state *drbg, struct drbg_string *pers,
1111 memset(drbg->C, 0, drbg_statelen(drbg)); 1108 memset(drbg->C, 0, drbg_statelen(drbg));
1112 } 1109 }
1113 1110
1114 ret = drbg->d_ops->update(drbg, &seedlist, reseed); 1111 ret = __drbg_seed(drbg, &seedlist, reseed);
1112
1113 /*
1114 * Clear the initial entropy buffer as the async call may not overwrite
1115 * that buffer for quite some time.
1116 */
1117 memzero_explicit(drbg->seed_buf, drbg->seed_buf_len);
1115 if (ret) 1118 if (ret)
1116 goto out; 1119 goto out;
1117 1120 /*
1118 drbg->seeded = true; 1121 * For all subsequent seeding calls, we only need the seed buffer
1119 /* 10.1.1.2 / 10.1.1.3 step 5 */ 1122 * equal to the security strength of the DRBG. We undo the calculation
1120 drbg->reseed_ctr = 1; 1123 * in drbg_alloc_state.
1124 */
1125 if (!reseed)
1126 drbg->seed_buf_len = drbg->seed_buf_len / 3 * 2;
1121 1127
1122out: 1128out:
1123 kzfree(entropy);
1124 return ret; 1129 return ret;
1125} 1130}
1126 1131
@@ -1143,6 +1148,8 @@ static inline void drbg_dealloc_state(struct drbg_state *drbg)
1143 drbg->prev = NULL; 1148 drbg->prev = NULL;
1144 drbg->fips_primed = false; 1149 drbg->fips_primed = false;
1145#endif 1150#endif
1151 kzfree(drbg->seed_buf);
1152 drbg->seed_buf = NULL;
1146} 1153}
1147 1154
1148/* 1155/*
@@ -1204,6 +1211,26 @@ static inline int drbg_alloc_state(struct drbg_state *drbg)
1204 if (!drbg->scratchpad) 1211 if (!drbg->scratchpad)
1205 goto err; 1212 goto err;
1206 } 1213 }
1214
1215 /*
1216 * Gather entropy equal to the security strength of the DRBG.
1217 * With a derivation function, a nonce is required in addition
1218 * to the entropy. A nonce must be at least 1/2 of the security
1219 * strength of the DRBG in size. Thus, entropy * nonce is 3/2
1220 * of the strength. The consideration of a nonce is only
1221 * applicable during initial seeding.
1222 */
1223 drbg->seed_buf_len = drbg_sec_strength(drbg->core->flags);
1224 if (!drbg->seed_buf_len) {
1225 ret = -EFAULT;
1226 goto err;
1227 }
1228 /* ensure we have sufficient buffer space for initial seed */
1229 drbg->seed_buf_len = ((drbg->seed_buf_len + 1) / 2) * 3;
1230 drbg->seed_buf = kzalloc(drbg->seed_buf_len, GFP_KERNEL);
1231 if (!drbg->seed_buf)
1232 goto err;
1233
1207 return 0; 1234 return 0;
1208 1235
1209err: 1236err: