Hello, Robert.
Thank you for your time and explanation.
On Mon, 26 Oct 2009, Robert Relyea wrote:
Given that, I am curious, why this code exists:
---- lg_GetPublicKey @ softoken/legacydb/lgattr.c ----
static NSSLOWKEYPublicKey *
lg_GetPublicKey(LGObjectCache *obj)
{
NSSLOWKEYPublicKey *pubKey;
NSSLOWKEYPrivateKey *privKey;
.......
privKey = lg_FindKeyByPublicKey( obj->sdb, &obj->dbKey );
if (privKey == NULL) {
return NULL;
}
pubKey = nsslowkey_ConvertToPublicKey(privKey);
This code exists because under certain conditions, NSS needs the public key (or
at least the existance of the public key) for each private key to work well.
NSS will work with tokens that do not store a public key with the private key,
but those tokens are not marked as 'publically readable certs', and thus NSS
needs to authenticate to them in order to properly identify certain
certificates. Softoken is automatically assumed to support this, but the
database did not have a place to store the certificate.
Unfortunately, I have poorly formulated my question.
I wanted to know, why, technically, there is a conversion "private" -> "public"
key at legacydb level. At the moment I have increased my understanding.
For those interested in legacydb internals, I want to publish some essential,
but non-obvious (AFAIK, not documented elsewhere) details about legacydb design
here:
-- "public key" objects are kept in "key3.db" file, not "cert8.db"
-- "public key" and "private key" objects aren't separate. They are kept only in
couples, as a single record in "key3.db". Exactly,
"key3.db" database record ::= { public_key RecordKey, private_key
RecordValue }
private_key ::= encrypted (password-based 3des) PKCS#8 PrivateKeyInfo
public_key ::= some raw part of public key ( without algorithm identifier
and/or parameters ). Exact presentation is chosen by softoken implementation
separately for each key type, namely:
X9.62 ECC ::= uncompressed ECPoint (note: *not* wrapped into octet
string, as for CKA_EC_POINT )
DSA ::= big-endian 'y' ( as for CKA_VALUE )
RSA ::= only part of key: big-endian 'modulus' ( as for CKA_MODULUS ),
'exponent' is omitted.
....
-- there is no guarantee that two different public keys won't clash RecordKeys in
"key3.db"
-- because if keys coupling, PKCS#11 calls:
C_DestroyObject( private key ) - deletes both public and private keys
from database.
C_DestroyObject( public key ) - does nothing, but returns fake CKR_OK.
-- keys coupling is also the cause why softoken wants CKA_NETSCAPE_DB on C_CreateObject(
private key, template ). Application must supply the raw public key value in
CKA_NETSCAPE_DB, because legacydb needs a record key for "key3.db".
It looks like public key (obj->dbKey) is used to find ... himself by extra
lookup for private key.
It couldn't be a problem, but this code implicitly assumes "there is a public key" inside
"private key". This is incorrect for GOST R 34.10-2001 private keys: PKCS#8
PrivateKeyInfo for GOST does *not* contain public part.
That's where the CKA_NETSCAPE_DB parameter comes in. It includes enough info to
be able to store the required public portions of the key in the database.
So, I am not sure, what is correct:
-- delete priv.key lookup from lg_GetPublicKey()
-- invent my own storage format for GOST keys, incompatible with PKCS#8
PrivateKeyInfo. This is much more patching of legacydb code.
Could you advice, please ?
Unfortunately the latter <...>
Based on investigation above, I suppose, I can just use public key from
RecordKey (available at LGObjectCache.dbKey) to reconstruct NSSLOWKEYPublicKey.
This approach was not used in legacydb until then, because a copy of public key
was always contained in a RecordValue.
Best regards,
--
Konstantin Andreev, software engineer.
Swemel JSC
--
dev-tech-crypto mailing list
dev-tech-crypto@lists.mozilla.org
https://lists.mozilla.org/listinfo/dev-tech-crypto