tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

lowkey.c (24512B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this
      3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 #include "lowkeyi.h"
      5 #include "secoid.h"
      6 #include "secitem.h"
      7 #include "secder.h"
      8 #include "base64.h"
      9 #include "secasn1.h"
     10 #include "secerr.h"
     11 #include "softoken.h"
     12 #include "ec.h"
     13 
     14 SEC_ASN1_MKSUB(SEC_AnyTemplate)
     15 SEC_ASN1_MKSUB(SEC_BitStringTemplate)
     16 SEC_ASN1_MKSUB(SEC_ObjectIDTemplate)
     17 SEC_ASN1_MKSUB(SECOID_AlgorithmIDTemplate)
     18 SEC_ASN1_MKSUB(SEC_OctetStringTemplate)
     19 
     20 const SEC_ASN1Template nsslowkey_AttributeTemplate[] = {
     21    { SEC_ASN1_SEQUENCE,
     22      0, NULL, sizeof(NSSLOWKEYAttribute) },
     23    { SEC_ASN1_OBJECT_ID, offsetof(NSSLOWKEYAttribute, attrType) },
     24    { SEC_ASN1_SET_OF | SEC_ASN1_XTRN,
     25      offsetof(NSSLOWKEYAttribute, attrValue),
     26      SEC_ASN1_SUB(SEC_AnyTemplate) },
     27    { 0 }
     28 };
     29 
     30 const SEC_ASN1Template nsslowkey_SetOfAttributeTemplate[] = {
     31    { SEC_ASN1_SET_OF, 0, nsslowkey_AttributeTemplate },
     32 };
     33 /* ASN1 Templates for new decoder/encoder */
     34 const SEC_ASN1Template nsslowkey_PrivateKeyInfoTemplate[] = {
     35    { SEC_ASN1_SEQUENCE,
     36      0, NULL, sizeof(NSSLOWKEYPrivateKeyInfo) },
     37    { SEC_ASN1_INTEGER,
     38      offsetof(NSSLOWKEYPrivateKeyInfo, version) },
     39    { SEC_ASN1_INLINE | SEC_ASN1_XTRN,
     40      offsetof(NSSLOWKEYPrivateKeyInfo, algorithm),
     41      SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
     42    { SEC_ASN1_OCTET_STRING,
     43      offsetof(NSSLOWKEYPrivateKeyInfo, privateKey) },
     44    { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0,
     45      offsetof(NSSLOWKEYPrivateKeyInfo, attributes),
     46      nsslowkey_SetOfAttributeTemplate },
     47    { 0 }
     48 };
     49 
     50 const SEC_ASN1Template nsslowkey_SubjectPublicKeyInfoTemplate[] = {
     51    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLOWKEYSubjectPublicKeyInfo) },
     52    { SEC_ASN1_INLINE | SEC_ASN1_XTRN,
     53      offsetof(NSSLOWKEYSubjectPublicKeyInfo, algorithm),
     54      SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
     55    { SEC_ASN1_BIT_STRING,
     56      offsetof(NSSLOWKEYSubjectPublicKeyInfo, subjectPublicKey) },
     57    { 0 }
     58 };
     59 
     60 const SEC_ASN1Template nsslowkey_RSAPublicKeyTemplate[] = {
     61    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLOWKEYPublicKey) },
     62    { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPublicKey, u.rsa.modulus) },
     63    { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPublicKey, u.rsa.publicExponent) },
     64    { 0 }
     65 };
     66 
     67 const SEC_ASN1Template nsslowkey_PQGParamsTemplate[] = {
     68    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(PQGParams) },
     69    { SEC_ASN1_INTEGER, offsetof(PQGParams, prime) },
     70    { SEC_ASN1_INTEGER, offsetof(PQGParams, subPrime) },
     71    { SEC_ASN1_INTEGER, offsetof(PQGParams, base) },
     72    { 0 }
     73 };
     74 
     75 const SEC_ASN1Template nsslowkey_RSAPrivateKeyTemplate[] = {
     76    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLOWKEYPrivateKey) },
     77    { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.rsa.version) },
     78    { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.rsa.modulus) },
     79    { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.rsa.publicExponent) },
     80    { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.rsa.privateExponent) },
     81    { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.rsa.prime1) },
     82    { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.rsa.prime2) },
     83    { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.rsa.exponent1) },
     84    { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.rsa.exponent2) },
     85    { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.rsa.coefficient) },
     86    { 0 }
     87 };
     88 
     89 const SEC_ASN1Template nsslowkey_DSAPrivateKeyTemplate[] = {
     90    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLOWKEYPrivateKey) },
     91    { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.dsa.publicValue) },
     92    { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.dsa.privateValue) },
     93    { 0 }
     94 };
     95 
     96 const SEC_ASN1Template nsslowkey_PQBothSeedAndPrivateKeyTemplate[] = {
     97    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLOWKEYPrivateKey) },
     98    { SEC_ASN1_OCTET_STRING, offsetof(NSSLOWKEYPrivateKey, u.genpq.seedItem) },
     99    { SEC_ASN1_OCTET_STRING, offsetof(NSSLOWKEYPrivateKey, u.genpq.keyItem) },
    100    { 0 }
    101 };
    102 
    103 const SEC_ASN1Template nsslowkey_PQSeedTemplate[] = {
    104    { SEC_ASN1_CONTEXT_SPECIFIC | 0,
    105      offsetof(NSSLOWKEYPrivateKey, u.genpq.seedItem),
    106      SEC_ASN1_SUB(SEC_OctetStringTemplate) },
    107    { 0 }
    108 };
    109 const SEC_ASN1Template nsslowkey_PQPrivateKeyTemplate[] = {
    110    { SEC_ASN1_OCTET_STRING, offsetof(NSSLOWKEYPrivateKey, u.genpq.keyItem) },
    111    { 0 }
    112 };
    113 
    114 const SEC_ASN1Template nsslowkey_DSAPrivateKeyExportTemplate[] = {
    115    { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.dsa.privateValue) },
    116 };
    117 
    118 const SEC_ASN1Template nsslowkey_DHPrivateKeyTemplate[] = {
    119    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLOWKEYPrivateKey) },
    120    { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.dh.publicValue) },
    121    { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.dh.privateValue) },
    122    { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.dh.base) },
    123    { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.dh.prime) },
    124    { 0 }
    125 };
    126 
    127 /* NOTE: The SECG specification allows the private key structure
    128 * to contain curve parameters but recommends that they be stored
    129 * in the PrivateKeyAlgorithmIdentifier field of the PrivateKeyInfo
    130 * instead.
    131 */
    132 const SEC_ASN1Template nsslowkey_ECPrivateKeyTemplate[] = {
    133    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLOWKEYPrivateKey) },
    134    { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey, u.ec.version) },
    135    { SEC_ASN1_OCTET_STRING,
    136      offsetof(NSSLOWKEYPrivateKey, u.ec.privateValue) },
    137    /* We only support named curves for which the parameters are
    138     * encoded as an object ID.
    139     */
    140    { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED |
    141          SEC_ASN1_EXPLICIT | SEC_ASN1_CONTEXT_SPECIFIC |
    142          SEC_ASN1_XTRN | 0,
    143      offsetof(NSSLOWKEYPrivateKey, u.ec.ecParams.curveOID),
    144      SEC_ASN1_SUB(SEC_ObjectIDTemplate) },
    145    { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED |
    146          SEC_ASN1_EXPLICIT | SEC_ASN1_CONTEXT_SPECIFIC |
    147          SEC_ASN1_XTRN | 1,
    148      offsetof(NSSLOWKEYPrivateKey, u.ec.publicValue),
    149      SEC_ASN1_SUB(SEC_BitStringTemplate) },
    150    { 0 }
    151 };
    152 /*
    153 * See bugzilla bug 125359
    154 * Since NSS (via PKCS#11) wants to handle big integers as unsigned ints,
    155 * all of the templates above that en/decode into integers must be converted
    156 * from ASN.1's signed integer type.  This is done by marking either the
    157 * source or destination (encoding or decoding, respectively) type as
    158 * siUnsignedInteger.
    159 */
    160 
    161 void
    162 prepare_low_rsa_priv_key_for_asn1(NSSLOWKEYPrivateKey *key)
    163 {
    164    key->u.rsa.modulus.type = siUnsignedInteger;
    165    key->u.rsa.publicExponent.type = siUnsignedInteger;
    166    key->u.rsa.privateExponent.type = siUnsignedInteger;
    167    key->u.rsa.prime1.type = siUnsignedInteger;
    168    key->u.rsa.prime2.type = siUnsignedInteger;
    169    key->u.rsa.exponent1.type = siUnsignedInteger;
    170    key->u.rsa.exponent2.type = siUnsignedInteger;
    171    key->u.rsa.coefficient.type = siUnsignedInteger;
    172 }
    173 
    174 void
    175 prepare_low_rsa_pub_key_for_asn1(NSSLOWKEYPublicKey *key)
    176 {
    177    key->u.rsa.modulus.type = siUnsignedInteger;
    178    key->u.rsa.publicExponent.type = siUnsignedInteger;
    179 }
    180 
    181 void
    182 prepare_low_pqg_params_for_asn1(PQGParams *params)
    183 {
    184    params->prime.type = siUnsignedInteger;
    185    params->subPrime.type = siUnsignedInteger;
    186    params->base.type = siUnsignedInteger;
    187 }
    188 
    189 void
    190 prepare_low_dsa_priv_key_for_asn1(NSSLOWKEYPrivateKey *key)
    191 {
    192    key->u.dsa.publicValue.type = siUnsignedInteger;
    193    key->u.dsa.privateValue.type = siUnsignedInteger;
    194    key->u.dsa.params.prime.type = siUnsignedInteger;
    195    key->u.dsa.params.subPrime.type = siUnsignedInteger;
    196    key->u.dsa.params.base.type = siUnsignedInteger;
    197 }
    198 
    199 void
    200 prepare_low_dsa_priv_key_export_for_asn1(NSSLOWKEYPrivateKey *key)
    201 {
    202    key->u.dsa.privateValue.type = siUnsignedInteger;
    203 }
    204 
    205 void
    206 prepare_low_dh_priv_key_for_asn1(NSSLOWKEYPrivateKey *key)
    207 {
    208    key->u.dh.prime.type = siUnsignedInteger;
    209    key->u.dh.base.type = siUnsignedInteger;
    210    key->u.dh.publicValue.type = siUnsignedInteger;
    211    key->u.dh.privateValue.type = siUnsignedInteger;
    212 }
    213 
    214 void
    215 prepare_low_ecparams_for_asn1(ECParams *params)
    216 {
    217    params->DEREncoding.type = siUnsignedInteger;
    218    params->curveOID.type = siUnsignedInteger;
    219 }
    220 
    221 void
    222 prepare_low_ec_priv_key_for_asn1(NSSLOWKEYPrivateKey *key)
    223 {
    224    key->u.ec.version.type = siUnsignedInteger;
    225    key->u.ec.ecParams.DEREncoding.type = siUnsignedInteger;
    226    key->u.ec.ecParams.curveOID.type = siUnsignedInteger;
    227    key->u.ec.privateValue.type = siUnsignedInteger;
    228    key->u.ec.publicValue.type = siUnsignedInteger;
    229 }
    230 
    231 void
    232 nsslowkey_DestroyPrivateKey(NSSLOWKEYPrivateKey *privk)
    233 {
    234    if (privk && privk->arena) {
    235        PORT_FreeArena(privk->arena, PR_TRUE);
    236    }
    237 }
    238 
    239 void
    240 nsslowkey_DestroyPublicKey(NSSLOWKEYPublicKey *pubk)
    241 {
    242    if (pubk && pubk->arena) {
    243        PORT_FreeArena(pubk->arena, PR_TRUE);
    244    }
    245 }
    246 unsigned
    247 nsslowkey_PublicModulusLen(NSSLOWKEYPublicKey *pubk)
    248 {
    249    /* interpret modulus length as key strength... in
    250     * fortezza that's the public key length */
    251 
    252    switch (pubk->keyType) {
    253        case NSSLOWKEYRSAKey:
    254            if (pubk->u.rsa.modulus.len == 0) {
    255                return 0;
    256            }
    257            if (pubk->u.rsa.modulus.data[0] == 0) {
    258                return pubk->u.rsa.modulus.len - 1;
    259            }
    260            return pubk->u.rsa.modulus.len;
    261        default:
    262            break;
    263    }
    264    return 0;
    265 }
    266 
    267 unsigned
    268 nsslowkey_PrivateModulusLen(NSSLOWKEYPrivateKey *privk)
    269 {
    270    switch (privk->keyType) {
    271        case NSSLOWKEYRSAKey:
    272            if (privk->u.rsa.modulus.len == 0) {
    273                return 0;
    274            }
    275            if (privk->u.rsa.modulus.data[0] == 0) {
    276                return privk->u.rsa.modulus.len - 1;
    277            }
    278            return privk->u.rsa.modulus.len;
    279        default:
    280            break;
    281    }
    282    return 0;
    283 }
    284 
    285 NSSLOWKEYPublicKey *
    286 nsslowkey_ConvertToPublicKey(NSSLOWKEYPrivateKey *privk)
    287 {
    288    NSSLOWKEYPublicKey *pubk;
    289    SECItem publicValue;
    290    PLArenaPool *arena;
    291 
    292    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
    293    if (arena == NULL) {
    294        PORT_SetError(SEC_ERROR_NO_MEMORY);
    295        return NULL;
    296    }
    297 
    298    switch (privk->keyType) {
    299        case NSSLOWKEYRSAKey:
    300        case NSSLOWKEYNullKey:
    301            pubk = (NSSLOWKEYPublicKey *)PORT_ArenaZAlloc(arena,
    302                                                          sizeof(NSSLOWKEYPublicKey));
    303            if (pubk != NULL) {
    304                SECStatus rv;
    305 
    306                pubk->arena = arena;
    307                pubk->keyType = privk->keyType;
    308                if (privk->keyType == NSSLOWKEYNullKey)
    309                    return pubk;
    310                rv = SECITEM_CopyItem(arena, &pubk->u.rsa.modulus,
    311                                      &privk->u.rsa.modulus);
    312                if (rv == SECSuccess) {
    313                    rv = SECITEM_CopyItem(arena, &pubk->u.rsa.publicExponent,
    314                                          &privk->u.rsa.publicExponent);
    315                    if (rv == SECSuccess)
    316                        return pubk;
    317                }
    318            } else {
    319                PORT_SetError(SEC_ERROR_NO_MEMORY);
    320            }
    321            break;
    322        case NSSLOWKEYDSAKey:
    323            pubk = (NSSLOWKEYPublicKey *)PORT_ArenaZAlloc(arena,
    324                                                          sizeof(NSSLOWKEYPublicKey));
    325            if (pubk != NULL) {
    326                SECStatus rv;
    327 
    328                pubk->arena = arena;
    329                pubk->keyType = privk->keyType;
    330                /* if the public key value doesn't exist, calculate it */
    331                if (privk->u.dsa.publicValue.len == 0) {
    332                    rv = DH_Derive(&privk->u.dsa.params.base, &privk->u.dsa.params.prime,
    333                                   &privk->u.dsa.privateValue, &publicValue, 0);
    334                    if (rv != SECSuccess) {
    335                        break;
    336                    }
    337                    rv = SECITEM_CopyItem(privk->arena, &privk->u.dsa.publicValue, &publicValue);
    338                    SECITEM_ZfreeItem(&publicValue, PR_FALSE);
    339                    if (rv != SECSuccess) {
    340                        break;
    341                    }
    342                }
    343                rv = SECITEM_CopyItem(arena, &pubk->u.dsa.publicValue,
    344                                      &privk->u.dsa.publicValue);
    345                if (rv != SECSuccess)
    346                    break;
    347                rv = SECITEM_CopyItem(arena, &pubk->u.dsa.params.prime,
    348                                      &privk->u.dsa.params.prime);
    349                if (rv != SECSuccess)
    350                    break;
    351                rv = SECITEM_CopyItem(arena, &pubk->u.dsa.params.subPrime,
    352                                      &privk->u.dsa.params.subPrime);
    353                if (rv != SECSuccess)
    354                    break;
    355                rv = SECITEM_CopyItem(arena, &pubk->u.dsa.params.base,
    356                                      &privk->u.dsa.params.base);
    357                if (rv == SECSuccess)
    358                    return pubk;
    359            }
    360            break;
    361        case NSSLOWKEYDHKey:
    362            pubk = (NSSLOWKEYPublicKey *)PORT_ArenaZAlloc(arena,
    363                                                          sizeof(NSSLOWKEYPublicKey));
    364            if (pubk != NULL) {
    365                SECStatus rv;
    366 
    367                pubk->arena = arena;
    368                pubk->keyType = privk->keyType;
    369                /* if the public key value doesn't exist, calculate it */
    370                if (privk->u.dh.publicValue.len == 0) {
    371                    rv = DH_Derive(&privk->u.dh.base, &privk->u.dh.prime,
    372                                   &privk->u.dh.privateValue, &publicValue, 0);
    373                    if (rv != SECSuccess) {
    374                        break;
    375                    }
    376                    rv = SECITEM_CopyItem(privk->arena, &privk->u.dh.publicValue, &publicValue);
    377                    SECITEM_ZfreeItem(&publicValue, PR_FALSE);
    378                    if (rv != SECSuccess) {
    379                        break;
    380                    }
    381                }
    382                rv = SECITEM_CopyItem(arena, &pubk->u.dh.publicValue,
    383                                      &privk->u.dh.publicValue);
    384                if (rv != SECSuccess)
    385                    break;
    386                rv = SECITEM_CopyItem(arena, &pubk->u.dh.prime,
    387                                      &privk->u.dh.prime);
    388                if (rv != SECSuccess)
    389                    break;
    390                rv = SECITEM_CopyItem(arena, &pubk->u.dh.base,
    391                                      &privk->u.dh.base);
    392                if (rv == SECSuccess)
    393                    return pubk;
    394            }
    395            break;
    396        case NSSLOWKEYECKey:
    397            pubk = (NSSLOWKEYPublicKey *)PORT_ArenaZAlloc(arena,
    398                                                          sizeof(NSSLOWKEYPublicKey));
    399            if (pubk != NULL) {
    400                SECStatus rv;
    401 
    402                pubk->arena = arena;
    403                pubk->keyType = privk->keyType;
    404 
    405                /* if the public key value doesn't exist, calculate it */
    406                if (privk->u.ec.publicValue.len == 0) {
    407                    /* Checking if it's an ed25519 or x25519 key.
    408                       If it's the case, we derive the public key using the private key. */
    409                    SECOidTag privKeyOIDTag = SECOID_FindOIDTag(&privk->u.ec.ecParams.curveOID);
    410                    if (privKeyOIDTag == SEC_OID_ED25519_PUBLIC_KEY) {
    411                        PORT_Memset(&privk->u.ec.publicValue, 0, sizeof(privk->u.ec.publicValue));
    412                        if (SECITEM_AllocItem(privk->arena, &privk->u.ec.publicValue, Ed25519_PUBLIC_KEYLEN) == NULL) {
    413                            break;
    414                        }
    415 
    416                        rv = ED_DerivePublicKey(&privk->u.ec.privateValue, &privk->u.ec.publicValue);
    417                        if (rv != CKR_OK) {
    418                            break;
    419                        }
    420                    } else if (privKeyOIDTag == SEC_OID_X25519) {
    421                        PORT_Memset(&privk->u.ec.publicValue, 0, sizeof(privk->u.ec.publicValue));
    422                        if (SECITEM_AllocItem(privk->arena, &privk->u.ec.publicValue, X25519_PUBLIC_KEYLEN) == NULL) {
    423                            break;
    424                        }
    425 
    426                        rv = X25519_DerivePublicKey(&privk->u.ec.privateValue, &privk->u.ec.publicValue);
    427                        if (rv != CKR_OK) {
    428                            break;
    429                        }
    430                    }
    431                }
    432 
    433                rv = SECITEM_CopyItem(arena, &pubk->u.ec.publicValue,
    434                                      &privk->u.ec.publicValue);
    435                if (rv != SECSuccess)
    436                    break;
    437                pubk->u.ec.ecParams.arena = arena;
    438                /* Copy the rest of the params */
    439                rv = EC_CopyParams(arena, &(pubk->u.ec.ecParams),
    440                                   &(privk->u.ec.ecParams));
    441                if (rv == SECSuccess)
    442                    return pubk;
    443            }
    444            break;
    445        case NSSLOWKEYMLDSAKey:
    446            pubk = (NSSLOWKEYPublicKey *)PORT_ArenaZAlloc(arena,
    447                                                          sizeof(NSSLOWKEYPublicKey));
    448            if (pubk != NULL) {
    449                SECStatus rv;
    450                SECItem seed = { siBuffer, NULL, 0 };
    451                MLDSAPrivateKey newPrivKey;
    452 
    453                pubk->arena = arena;
    454                pubk->keyType = privk->keyType;
    455 
    456                /* privatekey value is encoded (rho, K, tr, s1, s2, t0) */
    457                /* publickey value is encoded (rho, t1) */
    458                /* Future, we can calculate public key directly from
    459                 * privatekey value as follows :
    460                 * A^ = ExpandA(rho);
    461                 * t = NTT-1(A^ o NSS(s1)) + s2
    462                 * (t1, t0) = Power2Round(t)
    463                 * we now have rho and t1 so we can encode public key.
    464                 * these functions are all specified in FIPS-204. For now
    465                 * we just use the seed if it's a available and regenerate
    466                 * both keys, and discard the private key. */
    467                if (privk->u.mldsa.seedLen == 0) {
    468                    PORT_SetError(SEC_ERROR_PKCS11_FUNCTION_FAILED);
    469                    rv = SECFailure;
    470                    break;
    471                }
    472                seed.data = privk->u.mldsa.seed;
    473                seed.len = privk->u.mldsa.seedLen;
    474                rv = MLDSA_NewKey(privk->u.mldsa.paramSet, &seed,
    475                                  &newPrivKey, &pubk->u.mldsa);
    476                if (rv != SECSuccess) {
    477                    break;
    478                }
    479                PORT_SafeZero(&newPrivKey, sizeof(newPrivKey));
    480                return pubk;
    481            }
    482            break;
    483        /* No Fortezza in Low Key implementations (Fortezza keys aren't
    484         * stored in our data base */
    485        default:
    486            break;
    487    }
    488 
    489    PORT_FreeArena(arena, PR_TRUE);
    490    return NULL;
    491 }
    492 
    493 NSSLOWKEYPrivateKey *
    494 nsslowkey_CopyPrivateKey(NSSLOWKEYPrivateKey *privKey)
    495 {
    496    NSSLOWKEYPrivateKey *returnKey = NULL;
    497    SECStatus rv = SECFailure;
    498    PLArenaPool *poolp;
    499 
    500    if (!privKey) {
    501        return NULL;
    502    }
    503 
    504    poolp = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
    505    if (!poolp) {
    506        return NULL;
    507    }
    508 
    509    returnKey = (NSSLOWKEYPrivateKey *)PORT_ArenaZAlloc(poolp, sizeof(NSSLOWKEYPrivateKey));
    510    if (!returnKey) {
    511        rv = SECFailure;
    512        goto loser;
    513    }
    514 
    515    returnKey->keyType = privKey->keyType;
    516    returnKey->arena = poolp;
    517 
    518    switch (privKey->keyType) {
    519        case NSSLOWKEYRSAKey:
    520            rv = SECITEM_CopyItem(poolp, &(returnKey->u.rsa.modulus),
    521                                  &(privKey->u.rsa.modulus));
    522            if (rv != SECSuccess)
    523                break;
    524            rv = SECITEM_CopyItem(poolp, &(returnKey->u.rsa.version),
    525                                  &(privKey->u.rsa.version));
    526            if (rv != SECSuccess)
    527                break;
    528            rv = SECITEM_CopyItem(poolp, &(returnKey->u.rsa.publicExponent),
    529                                  &(privKey->u.rsa.publicExponent));
    530            if (rv != SECSuccess)
    531                break;
    532            rv = SECITEM_CopyItem(poolp, &(returnKey->u.rsa.privateExponent),
    533                                  &(privKey->u.rsa.privateExponent));
    534            if (rv != SECSuccess)
    535                break;
    536            rv = SECITEM_CopyItem(poolp, &(returnKey->u.rsa.prime1),
    537                                  &(privKey->u.rsa.prime1));
    538            if (rv != SECSuccess)
    539                break;
    540            rv = SECITEM_CopyItem(poolp, &(returnKey->u.rsa.prime2),
    541                                  &(privKey->u.rsa.prime2));
    542            if (rv != SECSuccess)
    543                break;
    544            rv = SECITEM_CopyItem(poolp, &(returnKey->u.rsa.exponent1),
    545                                  &(privKey->u.rsa.exponent1));
    546            if (rv != SECSuccess)
    547                break;
    548            rv = SECITEM_CopyItem(poolp, &(returnKey->u.rsa.exponent2),
    549                                  &(privKey->u.rsa.exponent2));
    550            if (rv != SECSuccess)
    551                break;
    552            rv = SECITEM_CopyItem(poolp, &(returnKey->u.rsa.coefficient),
    553                                  &(privKey->u.rsa.coefficient));
    554            if (rv != SECSuccess)
    555                break;
    556            break;
    557        case NSSLOWKEYDSAKey:
    558            rv = SECITEM_CopyItem(poolp, &(returnKey->u.dsa.publicValue),
    559                                  &(privKey->u.dsa.publicValue));
    560            if (rv != SECSuccess)
    561                break;
    562            rv = SECITEM_CopyItem(poolp, &(returnKey->u.dsa.privateValue),
    563                                  &(privKey->u.dsa.privateValue));
    564            if (rv != SECSuccess)
    565                break;
    566            returnKey->u.dsa.params.arena = poolp;
    567            rv = SECITEM_CopyItem(poolp, &(returnKey->u.dsa.params.prime),
    568                                  &(privKey->u.dsa.params.prime));
    569            if (rv != SECSuccess)
    570                break;
    571            rv = SECITEM_CopyItem(poolp, &(returnKey->u.dsa.params.subPrime),
    572                                  &(privKey->u.dsa.params.subPrime));
    573            if (rv != SECSuccess)
    574                break;
    575            rv = SECITEM_CopyItem(poolp, &(returnKey->u.dsa.params.base),
    576                                  &(privKey->u.dsa.params.base));
    577            if (rv != SECSuccess)
    578                break;
    579            break;
    580        case NSSLOWKEYDHKey:
    581            rv = SECITEM_CopyItem(poolp, &(returnKey->u.dh.publicValue),
    582                                  &(privKey->u.dh.publicValue));
    583            if (rv != SECSuccess)
    584                break;
    585            rv = SECITEM_CopyItem(poolp, &(returnKey->u.dh.privateValue),
    586                                  &(privKey->u.dh.privateValue));
    587            if (rv != SECSuccess)
    588                break;
    589            returnKey->u.dsa.params.arena = poolp;
    590            rv = SECITEM_CopyItem(poolp, &(returnKey->u.dh.prime),
    591                                  &(privKey->u.dh.prime));
    592            if (rv != SECSuccess)
    593                break;
    594            rv = SECITEM_CopyItem(poolp, &(returnKey->u.dh.base),
    595                                  &(privKey->u.dh.base));
    596            if (rv != SECSuccess)
    597                break;
    598            break;
    599        case NSSLOWKEYECKey:
    600            rv = SECITEM_CopyItem(poolp, &(returnKey->u.ec.version),
    601                                  &(privKey->u.ec.version));
    602            if (rv != SECSuccess)
    603                break;
    604            rv = SECITEM_CopyItem(poolp, &(returnKey->u.ec.publicValue),
    605                                  &(privKey->u.ec.publicValue));
    606            if (rv != SECSuccess)
    607                break;
    608            rv = SECITEM_CopyItem(poolp, &(returnKey->u.ec.privateValue),
    609                                  &(privKey->u.ec.privateValue));
    610            if (rv != SECSuccess)
    611                break;
    612            returnKey->u.ec.ecParams.arena = poolp;
    613            /* Copy the rest of the params */
    614            rv = EC_CopyParams(poolp, &(returnKey->u.ec.ecParams),
    615                               &(privKey->u.ec.ecParams));
    616            if (rv != SECSuccess)
    617                break;
    618            break;
    619        case NSSLOWKEYMLDSAKey:
    620            returnKey->u.mldsa = privKey->u.mldsa;
    621            rv = SECSuccess;
    622            break;
    623        default:
    624            rv = SECFailure;
    625    }
    626 
    627 loser:
    628 
    629    if (rv != SECSuccess) {
    630        PORT_FreeArena(poolp, PR_TRUE);
    631        returnKey = NULL;
    632    }
    633 
    634    return returnKey;
    635 }