acvptool: add hmacDRBG support

Change-Id: I63ecaaaa8ec339688c586a4b2d44e4b91b910b8f
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/49305
Commit-Queue: Adam Langley <agl@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
grpc-202302
Adam Langley 4 years ago committed by Boringssl LUCI CQ
parent a03c34c6d3
commit 25773430c0
  1. 5
      util/fipstools/acvp/ACVP.md
  2. 116
      util/fipstools/acvp/acvptool/subprocess/drbg.go
  3. BIN
      util/fipstools/acvp/acvptool/test/expected/hmacDRBG.bz2
  4. 1
      util/fipstools/acvp/acvptool/test/tests.json
  5. BIN
      util/fipstools/acvp/acvptool/test/vectors/hmacDRBG.bz2
  6. 98
      util/fipstools/acvp/acvptool/testmodulewrapper/hmac_drbg.go
  7. 103
      util/fipstools/acvp/acvptool/testmodulewrapper/hmac_drbg_test.go
  8. 93
      util/fipstools/acvp/acvptool/testmodulewrapper/testmodulewrapper.go

@ -66,6 +66,8 @@ The other commands are as follows. (Note that you only need to implement the com
| CMAC-AES | Number output bytes, key, message | MAC |
| CMAC-AES/verify | Key, message, claimed MAC | One-byte success flag |
| ctrDRBG/AES-256 | Output length, entropy, personalisation, ad1, ad2, nonce | Output |
| ctrDRBG-reseed/AES-256| Output length, entropy, personalisation, reseedAD, reseedEntropy, ad1, ad2, nonce | Output |
| ctrDRBG-pr/AES-256 | Output length, entropy, personalisation, ad1, entropy1, ad2, entropy2, nonce | Output |
| ECDH/&lt;CURVE&gt; | X, Y, private key | X, Y, shared key |
| ECDSA/keyGen | Curve name | Private key, X, Y |
| ECDSA/keyVer | Curve name, X, Y | Single-byte valid flag |
@ -79,6 +81,9 @@ The other commands are as follows. (Note that you only need to implement the com
| HMAC-SHA2-384 | Value to hash, key | Digest |
| HMAC-SHA2-512 | Value to hash, key | Digest |
| HMAC-SHA2-512/256 | Value to hash, key | Digest |
| hmacDRBG/&lt;HASH&gt;| Output length, entropy, personalisation, ad1, ad2, nonce | Output |
| hmacDRBG-reseed/&lt;HASH&gt;| Output length, entropy, personalisation, reseedAD, reseedEntropy, ad1, ad2, nonce | Output |
| hmacDRBG-pr/&lt;HASH&gt;| Output length, entropy, personalisation, ad1, entropy1, ad2, entropy2, nonce | Output |
| KDF-counter | Number output bytes, PRF name, counter location string, key, number of counter bits | Counter, output |
| RSA/keyGen | Modulus bit-size | e, p, q, n, d |
| RSA/sigGen/&lt;HASH&gt;/pkcs1v1.5 | Modulus bit-size | n, e, signature |

@ -40,18 +40,20 @@ type drbgTestGroup struct {
AdditionalDataBits uint64 `json:"additionalInputLen"`
RetBits uint64 `json:"returnedBitsLen"`
Tests []struct {
ID uint64 `json:"tcId"`
EntropyHex string `json:"entropyInput"`
NonceHex string `json:"nonce"`
PersonalizationHex string `json:"persoString"`
Other []struct {
AdditionalDataHex string `json:"additionalInput"`
EntropyHex string `json:"entropyInput"`
Use string `json:"intendedUse"`
} `json:"otherInput"`
ID uint64 `json:"tcId"`
EntropyHex string `json:"entropyInput"`
NonceHex string `json:"nonce"`
PersonalizationHex string `json:"persoString"`
Other []drbgOtherInput `json:"otherInput"`
} `json:"tests"`
}
type drbgOtherInput struct {
Use string `json:"intendedUse"`
AdditionalDataHex string `json:"additionalInput"`
EntropyHex string `json:"entropyInput"`
}
type drbgTestGroupResponse struct {
ID uint64 `json:"tgId"`
Tests []drbgTestResponse `json:"tests"`
@ -90,14 +92,6 @@ func (d *drbg) Process(vectorSet []byte, m Transactable) (interface{}, error) {
return nil, fmt.Errorf("test group %d specifies mode %q, which is not supported for the %s algorithm", group.ID, group.Mode, d.algo)
}
if group.PredictionResistance {
return nil, fmt.Errorf("Test group %d specifies prediction-resistance mode, which is not supported", group.ID)
}
if group.Reseed {
return nil, fmt.Errorf("Test group %d requests re-seeding, which is not supported", group.ID)
}
if group.RetBits%8 != 0 {
return nil, fmt.Errorf("Test group %d requests %d-bit outputs, but fractional-bytes are not supported", group.ID, group.RetBits)
}
@ -118,26 +112,38 @@ func (d *drbg) Process(vectorSet []byte, m Transactable) (interface{}, error) {
return nil, fmt.Errorf("failed to extract personalization hex from test case %d/%d: %s", group.ID, test.ID, err)
}
const numAdditionalInputs = 2
if len(test.Other) != numAdditionalInputs {
return nil, fmt.Errorf("test case %d/%d provides %d additional inputs, but subprocess only expects %d", group.ID, test.ID, len(test.Other), numAdditionalInputs)
}
outLen := group.RetBits / 8
var outLenBytes [4]byte
binary.LittleEndian.PutUint32(outLenBytes[:], uint32(outLen))
var additionalInputs [numAdditionalInputs][]byte
for i, other := range test.Other {
if other.Use != "generate" {
return nil, fmt.Errorf("other %d from test case %d/%d has use %q, but expected 'generate'", i, group.ID, test.ID, other.Use)
var result [][]byte
if group.PredictionResistance {
var a1, a2, a3, a4 []byte
if err := extractOtherInputs(test.Other, []drbgOtherInputExpectations{
{"generate", group.AdditionalDataBits, &a1, group.EntropyBits, &a2},
{"generate", group.AdditionalDataBits, &a3, group.EntropyBits, &a4}}); err != nil {
return nil, fmt.Errorf("failed to parse other inputs from test case %d/%d: %s", group.ID, test.ID, err)
}
result, err = m.Transact(d.algo+"-pr/"+group.Mode, 1, outLenBytes[:], ent, perso, a1, a2, a3, a4, nonce)
} else if group.Reseed {
var a1, a2, a3, a4 []byte
if err := extractOtherInputs(test.Other, []drbgOtherInputExpectations{
{"reSeed", group.AdditionalDataBits, &a1, group.EntropyBits, &a2},
{"generate", group.AdditionalDataBits, &a3, 0, nil},
{"generate", group.AdditionalDataBits, &a4, 0, nil}}); err != nil {
return nil, fmt.Errorf("failed to parse other inputs from test case %d/%d: %s", group.ID, test.ID, err)
}
additionalInputs[i], err = extractField(other.AdditionalDataHex, group.AdditionalDataBits)
if err != nil {
return nil, fmt.Errorf("failed to extract additional input %d from test case %d/%d: %s", i, group.ID, test.ID, err)
result, err = m.Transact(d.algo+"-reseed/"+group.Mode, 1, outLenBytes[:], ent, perso, a1, a2, a3, a4, nonce)
} else {
var a1, a2 []byte
if err := extractOtherInputs(test.Other, []drbgOtherInputExpectations{
{"generate", group.AdditionalDataBits, &a1, 0, nil},
{"generate", group.AdditionalDataBits, &a2, 0, nil}}); err != nil {
return nil, fmt.Errorf("failed to parse other inputs from test case %d/%d: %s", group.ID, test.ID, err)
}
result, err = m.Transact(d.algo+"/"+group.Mode, 1, outLenBytes[:], ent, perso, a1, a2, nonce)
}
outLen := group.RetBits / 8
var outLenBytes [4]byte
binary.LittleEndian.PutUint32(outLenBytes[:], uint32(outLen))
result, err := m.Transact(d.algo+"/"+group.Mode, 1, outLenBytes[:], ent, perso, additionalInputs[0], additionalInputs[1], nonce)
if err != nil {
return nil, fmt.Errorf("DRBG operation failed: %s", err)
}
@ -159,6 +165,52 @@ func (d *drbg) Process(vectorSet []byte, m Transactable) (interface{}, error) {
return ret, nil
}
type drbgOtherInputExpectations struct {
use string
additionalInputBitLen uint64
additionalInputOut *[]byte
entropyBitLen uint64
entropyOut *[]byte
}
func extractOtherInputs(inputs []drbgOtherInput, expected []drbgOtherInputExpectations) (err error) {
if len(inputs) != len(expected) {
return fmt.Errorf("found %d other inputs but %d were expected", len(inputs), len(expected))
}
for i := range inputs {
input, expect := &inputs[i], &expected[i]
if input.Use != expect.use {
return fmt.Errorf("other input #%d has type %q but expected %q", i, input.Use, expect.use)
}
if expect.additionalInputBitLen == 0 {
if len(input.AdditionalDataHex) != 0 {
return fmt.Errorf("other input #%d has unexpected additional input", i)
}
} else {
*expect.additionalInputOut, err = extractField(input.AdditionalDataHex, expect.additionalInputBitLen)
if err != nil {
return err
}
}
if expect.entropyBitLen == 0 {
if len(input.EntropyHex) != 0 {
return fmt.Errorf("other input #%d has unexpected entropy value", i)
}
} else {
*expect.entropyOut, err = extractField(input.EntropyHex, expect.entropyBitLen)
if err != nil {
return err
}
}
}
return nil
}
// validate the length and hex of a JSON field in test vectors
func extractField(fieldHex string, bits uint64) ([]byte, error) {
if uint64(len(fieldHex))*4 != bits {

@ -18,6 +18,7 @@
{"Wrapper": "modulewrapper", "In": "vectors/HMAC-SHA2-256.bz2", "Out": "expected/HMAC-SHA2-256.bz2"},
{"Wrapper": "modulewrapper", "In": "vectors/HMAC-SHA2-384.bz2", "Out": "expected/HMAC-SHA2-384.bz2"},
{"Wrapper": "modulewrapper", "In": "vectors/HMAC-SHA2-512.bz2", "Out": "expected/HMAC-SHA2-512.bz2"},
{"Wrapper": "testmodulewrapper", "In": "vectors/hmacDRBG.bz2", "Out": "expected/hmacDRBG.bz2"},
{"Wrapper": "testmodulewrapper", "In": "vectors/KAS-KDF.bz2", "Out": "expected/KAS-KDF.bz2"},
{"Wrapper": "modulewrapper", "In": "vectors/KAS-ECC-SSC.bz2"},
{"Wrapper": "modulewrapper", "In": "vectors/KAS-FFC-SSC.bz2"},

@ -0,0 +1,98 @@
// Copyright (c) 2021, Google Inc.
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
package main
import (
"crypto/hmac"
"crypto/sha256"
)
// See SP 800-90Ar1, section 10.1.2
type HMACDRBGSHA256 struct {
k, v [32]byte
}
func NewHMACDRBG(entropy, nonce, personalisation []byte) *HMACDRBGSHA256 {
ret := new(HMACDRBGSHA256)
ret.init(entropy, nonce, personalisation)
return ret
}
func (drbg *HMACDRBGSHA256) init(entropy, nonce, personalisation []byte) {
for i := range drbg.k {
drbg.k[i] = 0
}
for i := range drbg.v {
drbg.v[i] = 1
}
seed := make([]byte, 0, len(entropy)+len(nonce)+len(personalisation))
seed = append(seed, entropy...)
seed = append(seed, nonce...)
seed = append(seed, personalisation...)
drbg.update(seed)
}
func (drbg *HMACDRBGSHA256) update(data []byte) {
buf := make([]byte, 0, len(drbg.v)+1+len(data))
buf = append(buf, drbg.v[:]...)
buf = append(buf, 0)
buf = append(buf, data...)
mac := hmac.New(sha256.New, drbg.k[:])
mac.Write(buf)
mac.Sum(drbg.k[:0])
mac = hmac.New(sha256.New, drbg.k[:])
mac.Write(drbg.v[:])
mac.Sum(drbg.v[:0])
if len(data) > 0 {
copy(buf, drbg.v[:])
buf[len(drbg.v)] = 1
mac = hmac.New(sha256.New, drbg.k[:])
mac.Write(buf)
mac.Sum(drbg.k[:0])
mac = hmac.New(sha256.New, drbg.k[:])
mac.Write(drbg.v[:])
mac.Sum(drbg.v[:0])
}
}
func (drbg *HMACDRBGSHA256) Reseed(entropy, additionalInput []byte) {
buf := make([]byte, 0, len(entropy)+len(additionalInput))
buf = append(buf, entropy...)
buf = append(buf, additionalInput...)
drbg.update(buf)
}
func (drbg *HMACDRBGSHA256) Generate(out []byte, additionalInput []byte) {
if len(additionalInput) > 0 {
drbg.update(additionalInput)
}
done := 0
for done < len(out) {
mac := hmac.New(sha256.New, drbg.k[:])
mac.Write(drbg.v[:])
mac.Sum(drbg.v[:0])
done += copy(out[done:], drbg.v[:])
}
drbg.update(additionalInput)
}

@ -0,0 +1,103 @@
// Copyright (c) 2021, Google Inc.
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
package main
import (
"encoding/hex"
"testing"
)
/*
[SHA-256]
[PredictionResistance = False]
[EntropyInputLen = 256]
[NonceLen = 128]
[PersonalizationStringLen = 0]
[AdditionalInputLen = 0]
[ReturnedBitsLen = 1024]
COUNT = 0
EntropyInput = 06032cd5eed33f39265f49ecb142c511da9aff2af71203bffaf34a9ca5bd9c0d
Nonce = 0e66f71edc43e42a45ad3c6fc6cdc4df
PersonalizationString =
** INSTANTIATE:
V = 81e0d8830ed2d16f9b288a1cb289c5fab3f3c5c28131be7cafedcc7734604d34
Key = 17dc11c2389f5eeb9d0f6a5148a1ea83ee8a828f4f140ac78272a0da435fa121
EntropyInputReseed = 01920a4e669ed3a85ae8a33b35a74ad7fb2a6bb4cf395ce00334a9c9a5a5d552
AdditionalInputReseed =
** RESEED:
V = c246fa97570ba2b9d9e5b453fe4632366f146fbd8491146563eb463c9eafe50c
Key = ca43e73325de43c41d7e0a7a3163fb04061b09fcee4c7b8884e969e3bdfdff9a
AdditionalInput =
** GENERATE (FIRST CALL):
V = df67d0816d6a8f3b73ba7638ea113bef0e33a1da451272ef1472211fb31c1cd6
Key = 8be4c7f9f249d5af2c6345a8f07af14be1d7adc2b9892286ffe37760d8aa5a1b
AdditionalInput =
ReturnedBits = 76fc79fe9b50beccc991a11b5635783a83536add03c157fb30645e611c2898bb2b1bc215000209208cd506cb28da2a51bdb03826aaf2bd2335d576d519160842e7158ad0949d1a9ec3e66ea1b1a064b005de914eac2e9d4f2d72a8616a80225422918250ff66a41bd2f864a6a38cc5b6499dc43f7f2bd09e1e0f8f5885935124
** GENERATE (SECOND CALL):
V = 80524881711e89a61e6fe7169581e50fb9ad642f3dff48fba5773352fa04cec3
Key = 5ed31bc06cc4f3a97f7f34929b0558b0c34de1f4bd1cef456a8364140e2d9f41
*/
func TestHMACDRBG(t *testing.T) {
drbg := NewHMACDRBG(fromHex("06032cd5eed33f39265f49ecb142c511da9aff2af71203bffaf34a9ca5bd9c0d"),
fromHex("0e66f71edc43e42a45ad3c6fc6cdc4df"),
nil)
drbg.Reseed(fromHex("01920a4e669ed3a85ae8a33b35a74ad7fb2a6bb4cf395ce00334a9c9a5a5d552"), nil)
var out [1024 / 8]byte
drbg.Generate(out[:], nil)
drbg.Generate(out[:], nil)
if hex.EncodeToString(out[:]) != "76fc79fe9b50beccc991a11b5635783a83536add03c157fb30645e611c2898bb2b1bc215000209208cd506cb28da2a51bdb03826aaf2bd2335d576d519160842e7158ad0949d1a9ec3e66ea1b1a064b005de914eac2e9d4f2d72a8616a80225422918250ff66a41bd2f864a6a38cc5b6499dc43f7f2bd09e1e0f8f5885935124" {
t.Errorf("Incorrect result: %x", out)
}
}
/*
EntropyInput = 6c1f4bffc476e488fb57eb80dc106cf2b417bad22b196baa6346958256db490f
Nonce = 5f1b92223e3909e43677da2f588a6d19
PersonalizationString =
AdditionalInput = e6cd940610375e504fa80406120b34d498b022393436e910c0ba2560603fd066
EntropyInputPR = abaca65695bd5d289880453850fc8289b76f78b43f970ed32f4125a941165515
AdditionalInput = d20082c5bdf6f6711af391e7d01046b9d3610827de63aa2671a5f5ad07b90841
EntropyInputPR = 4a39b666cf861816d7d82ef6e23f70f149d74d9bd499eea19b622e751c43d839
ReturnedBits = d3c36e4ae25ff21a95a157a89f13eb976362a695ea755f0465ed4a7bb20c5cb3
*/
func TestHMACDRBGPredictionResistance(t *testing.T) {
drbg := NewHMACDRBG(fromHex("6c1f4bffc476e488fb57eb80dc106cf2b417bad22b196baa6346958256db490f"),
fromHex("5f1b92223e3909e43677da2f588a6d19"),
nil)
var out [32]byte
drbg.Reseed(fromHex("abaca65695bd5d289880453850fc8289b76f78b43f970ed32f4125a941165515"), fromHex("e6cd940610375e504fa80406120b34d498b022393436e910c0ba2560603fd066"))
drbg.Generate(out[:], nil)
drbg.Reseed(fromHex("4a39b666cf861816d7d82ef6e23f70f149d74d9bd499eea19b622e751c43d839"), fromHex("d20082c5bdf6f6711af391e7d01046b9d3610827de63aa2671a5f5ad07b90841"))
drbg.Generate(out[:], nil)
if hex.EncodeToString(out[:]) != "d3c36e4ae25ff21a95a157a89f13eb976362a695ea755f0465ed4a7bb20c5cb3" {
t.Errorf("Incorrect result: %x", out)
}
}
func fromHex(h string) []byte {
ret, err := hex.DecodeString(h)
if err != nil {
panic(err)
}
return ret
}

@ -1,3 +1,17 @@
// Copyright (c) 2021, Google Inc.
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
// testmodulewrapper is a modulewrapper binary that works with acvptool and
// implements the primitives that BoringSSL's modulewrapper doesn't, so that
// we have something that can exercise all the code in avcptool.
@ -21,11 +35,13 @@ import (
)
var handlers = map[string]func([][]byte) error{
"getConfig": getConfig,
"KDF-counter": kdfCounter,
"AES-XTS/encrypt": xtsEncrypt,
"AES-XTS/decrypt": xtsDecrypt,
"HKDF/SHA2-256": hkdfMAC,
"getConfig": getConfig,
"KDF-counter": kdfCounter,
"AES-XTS/encrypt": xtsEncrypt,
"AES-XTS/decrypt": xtsDecrypt,
"HKDF/SHA2-256": hkdfMAC,
"hmacDRBG-reseed/SHA2-256": hmacDRBGReseed,
"hmacDRBG-pr/SHA2-256": hmacDRBGPredictionResistance,
}
func getConfig(args [][]byte) error {
@ -104,6 +120,28 @@ func getConfig(args [][]byte) error {
}],
"l": 256,
"z": [256, 384]
}, {
"algorithm": "hmacDRBG",
"revision": "1.0",
"predResistanceEnabled": [false, true],
"reseedImplemented": true,
"capabilities": [{
"mode": "SHA2-256",
"derFuncEnabled": false,
"entropyInputLen": [
256
],
"nonceLen": [
128
],
"persoStringLen": [
256
],
"additionalInputLen": [
256
],
"returnedBitsLen": 256
}]
}
]`))
}
@ -246,8 +284,51 @@ func hkdfMAC(args [][]byte) error {
return reply(ret)
}
func hmacDRBGReseed(args [][]byte) error {
if len(args) != 8 {
return fmt.Errorf("hmacDRBG received %d args, wanted 8", len(args))
}
outLenBytes, entropy, personalisation, reseedAdditionalData, reseedEntropy, additionalData1, additionalData2, nonce := args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]
if len(outLenBytes) != 4 {
return fmt.Errorf("uint32 length was %d bytes long", len(outLenBytes))
}
outLen := binary.LittleEndian.Uint32(outLenBytes)
out := make([]byte, outLen)
drbg := NewHMACDRBG(entropy, nonce, personalisation)
drbg.Reseed(reseedEntropy, reseedAdditionalData)
drbg.Generate(out, additionalData1)
drbg.Generate(out, additionalData2)
return reply(out)
}
func hmacDRBGPredictionResistance(args [][]byte) error {
if len(args) != 8 {
return fmt.Errorf("hmacDRBG received %d args, wanted 8", len(args))
}
outLenBytes, entropy, personalisation, additionalData1, entropy1, additionalData2, entropy2, nonce := args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]
if len(outLenBytes) != 4 {
return fmt.Errorf("uint32 length was %d bytes long", len(outLenBytes))
}
outLen := binary.LittleEndian.Uint32(outLenBytes)
out := make([]byte, outLen)
drbg := NewHMACDRBG(entropy, nonce, personalisation)
drbg.Reseed(entropy1, additionalData1)
drbg.Generate(out, nil)
drbg.Reseed(entropy2, additionalData2)
drbg.Generate(out, nil)
return reply(out)
}
const (
maxArgs = 8
maxArgs = 9
maxArgLength = 1 << 20
maxNameLength = 30
)

Loading…
Cancel
Save