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

Reply via email to