[Cryptech Tech] Key wrap in HW

Rob Austein sra at hactrn.net
Mon Jun 18 17:04:37 UTC 2018

On Mon, 18 Jun 2018 10:46:05 -0400, Joachim =?utf-8?q?Str=C3=B6mbergson?= wrote:
> The key issue I see is how key wrapping is used in the Alpha. Are we
> wrapping/unwrapping single keys? Or are wrapping/unwrapping
> performed on a bunch of keys as they belong to the same plaintext?
> If  we do wrap/unwrap on per-key basis the size of the processing
> buffer will not be that big, and we can implement this with the
> block memories in the FPGA without any problems. 8192 bits for
> example should be no problem.

It's all single keys.  Not sure I even understand your "bunch of keys"
model but am pretty sure it's not what we're doing. :)

Plaintext for a key is bit larger than just the raw bits.  What we're
wrapping and unwrapping is the ASN.1 DER encoding of a PKCS #8
PrivateKeyInfo.  Basically, this is the blob which would go into the
encryptedData OCTET STRING in an PKCS #8 EncryptedPrivateKeyInfo, but
since the keystore only uses one wrapping algorithm, the outermost
layer of ASN.1 encapsulation doesn't buy us anything, so we omit it.

Also, for RSA keys, there are six extra (non-standard) key components
stuffed into the ASN.1 to support faster ModExp (long story, explained
here a while back, summary is that this buys us a 2x speedup).  These
extra fields are represented as ASN.1 OPTIONAL IMPLICIT PRIVATE OCTET
STRINGs, which is ASN.1 technobabble meaning that we store byte
strings with special ASN.1 tagging which identifies these fields as
Weird Stuff; since we never export these fields (even on key backup),
this is pretty safe, and the format lets us use a single ASN.1 parser
for both normal RSA keys and RSA keys with these extra fields added.

There's a certain amount of voodoo involved in figuring out the
current size of a maximum length unwrapped key, and it's not worth
spending too much effort trying to compute an exact byte count anyway.
The buffer size we use in the C code is determined by some code in
sw/libhal/hal_internal.h, quoted below for convenience.

 * Sizes for PKCS #8 encoded private keys.  This may not be exact due
 * to ASN.1 INTEGER encoding rules, but should be good enough for
 * buffer sizing.
 * 2048-bit RSA:        1219 bytes
 * 4096-bit RSA:        2373 bytes
 * 8192-bit RSA:        4679 bytes
 * EC P-256:             138 bytes
 * EC P-384:             185 bytes
 * EC P-521:             240 bytes
 * Plus extra space for pre-computed speed-up factors specific to our
 * Verilog implementation, which we store as fixed-length byte strings.
 * Plus we need a bit of AES-keywrap overhead, since we're storing the
 * wrapped form (see hal_aes_keywrap_cyphertext_length()).
 * Length check warning moved to ks.h since size of keystore blocks is
 * internal to the keystore implementation.

#define HAL_KS_WRAPPED_KEYSIZE  ((2373 + 6 * 4096 / 8 + 6 * 4 + 15) & ~7)

More information about the Tech mailing list