|
7 | 7 | "errors" |
8 | 8 | "hash" |
9 | 9 | "io" |
| 10 | + "runtime" |
| 11 | + "sync/atomic" |
10 | 12 | "time" |
11 | 13 |
|
12 | 14 | "github.com/emmansun/gmsm/sm3" |
@@ -226,6 +228,8 @@ type DRBG interface { |
226 | 228 | Generate(b, additional []byte) error |
227 | 229 | // MaxBytesPerRequest return max bytes per request |
228 | 230 | MaxBytesPerRequest() int |
| 231 | + // Destroy internal state |
| 232 | + Destroy() |
229 | 233 | } |
230 | 234 |
|
231 | 235 | type BaseDrbg struct { |
@@ -258,6 +262,26 @@ func (hd *BaseDrbg) setSecurityLevel(securityLevel SecurityLevel) { |
258 | 262 | } |
259 | 263 | } |
260 | 264 |
|
| 265 | +// Destroy 对 GM/T 0105-2021 B.2、E.2 对内部状态进行清零处理 |
| 266 | +// 内部状态组成为 {V,C, reseed_counter, last_reseed_time,reseed_interval_in_counter, reseed_interval_in_time} |
| 267 | +// 内部状态组成为 {V,Key, reseed_counter, last_reseed_time,reseed_interval_in_counter, reseed_interval_in_time} |
| 268 | +func (cd *BaseDrbg) Destroy() { |
| 269 | + setZero(cd.v) |
| 270 | + cd.seedLength = 0 |
| 271 | + for i := 0; i < 3; i++ { |
| 272 | + // 使用原子操作防止编译器优化 |
| 273 | + atomic.StoreUint64(&cd.reseedCounter, 0xFFFFFFFFFFFFFFFF) |
| 274 | + atomic.StoreUint64(&cd.reseedCounter, 0x00) |
| 275 | + atomic.StoreUint64(&cd.reseedIntervalInCounter, 0xFFFFFFFFFFFFFFFF) |
| 276 | + atomic.StoreUint64(&cd.reseedIntervalInCounter, 0x00) |
| 277 | + // 将 reseedIntervalInTime 设置内存屏障,防止编译器优化 |
| 278 | + cd.reseedIntervalInTime = time.Duration(1<<63 - 1) |
| 279 | + runtime.KeepAlive(&cd.reseedIntervalInTime) |
| 280 | + cd.reseedIntervalInTime = time.Duration(0) |
| 281 | + cd.reseedTime = time.Now() |
| 282 | + } |
| 283 | +} |
| 284 | + |
261 | 285 | // Set security_strength to the lowest security strength greater than or equal to |
262 | 286 | // requested_instantiation_security_strength from the set {112, 128, 192, 256}. |
263 | 287 | func selectSecurityStrength(requested int) int { |
@@ -292,3 +316,26 @@ func addOne(data []byte, len int) { |
292 | 316 | temp >>= 8 |
293 | 317 | } |
294 | 318 | } |
| 319 | + |
| 320 | +// setZero tries best to clear the sensitive data in memory by overwriting it with 0xFF and 0 for 3 times. |
| 321 | +// - data: the byte slice to be cleared. |
| 322 | +func setZero(data []byte) { |
| 323 | + if data == nil { |
| 324 | + return |
| 325 | + } |
| 326 | + for j := 0; j < 3; j++ { |
| 327 | + // 先写入0xFF |
| 328 | + for i := range data { |
| 329 | + data[i] = 0xFF |
| 330 | + } |
| 331 | + // 内存屏障,确保写入0xFF完成 |
| 332 | + runtime.KeepAlive(data) |
| 333 | + |
| 334 | + // 再写入0 |
| 335 | + for i := range data { |
| 336 | + data[i] = 0 |
| 337 | + } |
| 338 | + // 再次内存屏障,确保写入0完成 |
| 339 | + runtime.KeepAlive(data) |
| 340 | + } |
| 341 | +} |
0 commit comments