Back to index

lightning-sunbird  0.9+nobinonly
lowkey.c
Go to the documentation of this file.
00001 /* ***** BEGIN LICENSE BLOCK *****
00002  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00003  *
00004  * The contents of this file are subject to the Mozilla Public License Version
00005  * 1.1 (the "License"); you may not use this file except in compliance with
00006  * the License. You may obtain a copy of the License at
00007  * http://www.mozilla.org/MPL/
00008  *
00009  * Software distributed under the License is distributed on an "AS IS" basis,
00010  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00011  * for the specific language governing rights and limitations under the
00012  * License.
00013  *
00014  * The Original Code is the Netscape security libraries.
00015  *
00016  * The Initial Developer of the Original Code is
00017  * Netscape Communications Corporation.
00018  * Portions created by the Initial Developer are Copyright (C) 1994-2000
00019  * the Initial Developer. All Rights Reserved.
00020  *
00021  * Contributor(s):
00022  *   Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either the GNU General Public License Version 2 or later (the "GPL"), or
00026  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 #include "lowkeyi.h"
00038 #include "secoid.h"
00039 #include "secitem.h"
00040 #include "secder.h"
00041 #include "base64.h"
00042 #include "secasn1.h"
00043 #include "pcert.h"
00044 #include "secerr.h"
00045 
00046 #ifdef NSS_ENABLE_ECC
00047 extern SECStatus EC_CopyParams(PRArenaPool *arena, 
00048                             ECParams *dstParams,
00049                             const ECParams *srcParams);
00050 #endif
00051 
00052 const SEC_ASN1Template nsslowkey_PQGParamsTemplate[] = {
00053     { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(PQGParams) },
00054     { SEC_ASN1_INTEGER, offsetof(PQGParams,prime) },
00055     { SEC_ASN1_INTEGER, offsetof(PQGParams,subPrime) },
00056     { SEC_ASN1_INTEGER, offsetof(PQGParams,base) },
00057     { 0, }
00058 };
00059 
00060 const SEC_ASN1Template nsslowkey_RSAPrivateKeyTemplate[] = {
00061     { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLOWKEYPrivateKey) },
00062     { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.version) },
00063     { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.modulus) },
00064     { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.publicExponent) },
00065     { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.privateExponent) },
00066     { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.prime1) },
00067     { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.prime2) },
00068     { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.exponent1) },
00069     { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.exponent2) },
00070     { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.coefficient) },
00071     { 0 }                                                                     
00072 };                                                                            
00073 
00074 
00075 const SEC_ASN1Template nsslowkey_DSAPrivateKeyTemplate[] = {
00076     { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLOWKEYPrivateKey) },
00077     { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.dsa.publicValue) },
00078     { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.dsa.privateValue) },
00079     { 0, }
00080 };
00081 
00082 const SEC_ASN1Template nsslowkey_DSAPrivateKeyExportTemplate[] = {
00083     { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.dsa.privateValue) },
00084 };
00085 
00086 const SEC_ASN1Template nsslowkey_DHPrivateKeyTemplate[] = {
00087     { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLOWKEYPrivateKey) },
00088     { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.dh.publicValue) },
00089     { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.dh.privateValue) },
00090     { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.dh.base) },
00091     { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.dh.prime) },
00092     { 0, }
00093 };
00094 
00095 #ifdef NSS_ENABLE_ECC
00096 
00097 /* XXX This is just a placeholder for later when we support
00098  * generic curves and need full-blown support for parsing EC
00099  * parameters. For now, we only support named curves in which
00100  * EC params are simply encoded as an object ID and we don't
00101  * use nsslowkey_ECParamsTemplate.
00102  */
00103 const SEC_ASN1Template nsslowkey_ECParamsTemplate[] = {
00104     { SEC_ASN1_CHOICE, offsetof(ECParams,type), NULL, sizeof(ECParams) },
00105     { SEC_ASN1_OBJECT_ID, offsetof(ECParams,curveOID), NULL, ec_params_named },
00106     { 0, }
00107 };
00108 
00109 
00110 /* NOTE: The SECG specification allows the private key structure
00111  * to contain curve parameters but recommends that they be stored
00112  * in the PrivateKeyAlgorithmIdentifier field of the PrivateKeyInfo
00113  * instead.
00114  */
00115 const SEC_ASN1Template nsslowkey_ECPrivateKeyTemplate[] = {
00116     { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLOWKEYPrivateKey) },
00117     { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.ec.version) },
00118     { SEC_ASN1_OCTET_STRING, 
00119       offsetof(NSSLOWKEYPrivateKey,u.ec.privateValue) },
00120     /* XXX The following template works for now since we only
00121      * support named curves for which the parameters are
00122      * encoded as an object ID. When we support generic curves,
00123      * we'll need to define nsslowkey_ECParamsTemplate
00124      */
00125 #if 1
00126     { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED |
00127       SEC_ASN1_EXPLICIT | SEC_ASN1_CONTEXT_SPECIFIC | 0, 
00128       offsetof(NSSLOWKEYPrivateKey,u.ec.ecParams.curveOID), 
00129       SEC_ObjectIDTemplate }, 
00130 #else
00131     { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED |
00132       SEC_ASN1_EXPLICIT | SEC_ASN1_CONTEXT_SPECIFIC | 0, 
00133       offsetof(NSSLOWKEYPrivateKey,u.ec.ecParams), 
00134       nsslowkey_ECParamsTemplate }, 
00135 #endif
00136     { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED |
00137       SEC_ASN1_EXPLICIT | SEC_ASN1_CONTEXT_SPECIFIC | 1, 
00138       offsetof(NSSLOWKEYPrivateKey,u.ec.publicValue),
00139       SEC_BitStringTemplate }, 
00140     { 0, }
00141 };
00142 #endif /* NSS_ENABLE_ECC */
00143 /*
00144  * See bugzilla bug 125359
00145  * Since NSS (via PKCS#11) wants to handle big integers as unsigned ints,
00146  * all of the templates above that en/decode into integers must be converted
00147  * from ASN.1's signed integer type.  This is done by marking either the
00148  * source or destination (encoding or decoding, respectively) type as
00149  * siUnsignedInteger.
00150  */
00151 
00152 void
00153 prepare_low_rsa_priv_key_for_asn1(NSSLOWKEYPrivateKey *key)
00154 {
00155     key->u.rsa.modulus.type = siUnsignedInteger;
00156     key->u.rsa.publicExponent.type = siUnsignedInteger;
00157     key->u.rsa.privateExponent.type = siUnsignedInteger;
00158     key->u.rsa.prime1.type = siUnsignedInteger;
00159     key->u.rsa.prime2.type = siUnsignedInteger;
00160     key->u.rsa.exponent1.type = siUnsignedInteger;
00161     key->u.rsa.exponent2.type = siUnsignedInteger;
00162     key->u.rsa.coefficient.type = siUnsignedInteger;
00163 }
00164 
00165 void
00166 prepare_low_pqg_params_for_asn1(PQGParams *params)
00167 {
00168     params->prime.type = siUnsignedInteger;
00169     params->subPrime.type = siUnsignedInteger;
00170     params->base.type = siUnsignedInteger;
00171 }
00172 
00173 void
00174 prepare_low_dsa_priv_key_for_asn1(NSSLOWKEYPrivateKey *key)
00175 {
00176     key->u.dsa.publicValue.type = siUnsignedInteger;
00177     key->u.dsa.privateValue.type = siUnsignedInteger;
00178     key->u.dsa.params.prime.type = siUnsignedInteger;
00179     key->u.dsa.params.subPrime.type = siUnsignedInteger;
00180     key->u.dsa.params.base.type = siUnsignedInteger;
00181 }
00182 
00183 void
00184 prepare_low_dsa_priv_key_export_for_asn1(NSSLOWKEYPrivateKey *key)
00185 {
00186     key->u.dsa.privateValue.type = siUnsignedInteger;
00187 }
00188 
00189 void
00190 prepare_low_dh_priv_key_for_asn1(NSSLOWKEYPrivateKey *key)
00191 {
00192     key->u.dh.prime.type = siUnsignedInteger;
00193     key->u.dh.base.type = siUnsignedInteger;
00194     key->u.dh.publicValue.type = siUnsignedInteger;
00195     key->u.dh.privateValue.type = siUnsignedInteger;
00196 }
00197 
00198 #ifdef NSS_ENABLE_ECC
00199 void
00200 prepare_low_ecparams_for_asn1(ECParams *params)
00201 {
00202     params->DEREncoding.type = siUnsignedInteger;
00203     params->curveOID.type = siUnsignedInteger;
00204 }
00205 
00206 void
00207 prepare_low_ec_priv_key_for_asn1(NSSLOWKEYPrivateKey *key)
00208 {
00209     key->u.ec.version.type = siUnsignedInteger;
00210     key->u.ec.ecParams.DEREncoding.type = siUnsignedInteger;
00211     key->u.ec.ecParams.curveOID.type = siUnsignedInteger;
00212     key->u.ec.privateValue.type = siUnsignedInteger;
00213     key->u.ec.publicValue.type = siUnsignedInteger;
00214 }
00215 #endif /* NSS_ENABLE_ECC */
00216 
00217 void
00218 nsslowkey_DestroyPrivateKey(NSSLOWKEYPrivateKey *privk)
00219 {
00220     if (privk && privk->arena) {
00221        PORT_FreeArena(privk->arena, PR_TRUE);
00222     }
00223 }
00224 
00225 void
00226 nsslowkey_DestroyPublicKey(NSSLOWKEYPublicKey *pubk)
00227 {
00228     if (pubk && pubk->arena) {
00229        PORT_FreeArena(pubk->arena, PR_FALSE);
00230     }
00231 }
00232 unsigned
00233 nsslowkey_PublicModulusLen(NSSLOWKEYPublicKey *pubk)
00234 {
00235     unsigned char b0;
00236 
00237     /* interpret modulus length as key strength... in
00238      * fortezza that's the public key length */
00239 
00240     switch (pubk->keyType) {
00241     case NSSLOWKEYRSAKey:
00242        b0 = pubk->u.rsa.modulus.data[0];
00243        return b0 ? pubk->u.rsa.modulus.len : pubk->u.rsa.modulus.len - 1;
00244     default:
00245        break;
00246     }
00247     return 0;
00248 }
00249 
00250 unsigned
00251 nsslowkey_PrivateModulusLen(NSSLOWKEYPrivateKey *privk)
00252 {
00253 
00254     unsigned char b0;
00255 
00256     switch (privk->keyType) {
00257     case NSSLOWKEYRSAKey:
00258        b0 = privk->u.rsa.modulus.data[0];
00259        return b0 ? privk->u.rsa.modulus.len : privk->u.rsa.modulus.len - 1;
00260     default:
00261        break;
00262     }
00263     return 0;
00264 }
00265 
00266 NSSLOWKEYPublicKey *
00267 nsslowkey_ConvertToPublicKey(NSSLOWKEYPrivateKey *privk)
00268 {
00269     NSSLOWKEYPublicKey *pubk;
00270     PLArenaPool *arena;
00271 
00272 
00273     arena = PORT_NewArena (DER_DEFAULT_CHUNKSIZE);
00274     if (arena == NULL) {
00275         PORT_SetError (SEC_ERROR_NO_MEMORY);
00276         return NULL;
00277     }
00278 
00279     switch(privk->keyType) {
00280       case NSSLOWKEYRSAKey:
00281       case NSSLOWKEYNullKey:
00282        pubk = (NSSLOWKEYPublicKey *)PORT_ArenaZAlloc(arena,
00283                                           sizeof (NSSLOWKEYPublicKey));
00284        if (pubk != NULL) {
00285            SECStatus rv;
00286 
00287            pubk->arena = arena;
00288            pubk->keyType = privk->keyType;
00289            if (privk->keyType == NSSLOWKEYNullKey) return pubk;
00290            rv = SECITEM_CopyItem(arena, &pubk->u.rsa.modulus,
00291                               &privk->u.rsa.modulus);
00292            if (rv == SECSuccess) {
00293               rv = SECITEM_CopyItem (arena, &pubk->u.rsa.publicExponent,
00294                                    &privk->u.rsa.publicExponent);
00295               if (rv == SECSuccess)
00296                   return pubk;
00297            }
00298        } else {
00299            PORT_SetError (SEC_ERROR_NO_MEMORY);
00300        }
00301        break;
00302       case NSSLOWKEYDSAKey:
00303        pubk = (NSSLOWKEYPublicKey *)PORT_ArenaZAlloc(arena,
00304                                               sizeof(NSSLOWKEYPublicKey));
00305        if (pubk != NULL) {
00306            SECStatus rv;
00307 
00308            pubk->arena = arena;
00309            pubk->keyType = privk->keyType;
00310            rv = SECITEM_CopyItem(arena, &pubk->u.dsa.publicValue,
00311                               &privk->u.dsa.publicValue);
00312            if (rv != SECSuccess) break;
00313            rv = SECITEM_CopyItem(arena, &pubk->u.dsa.params.prime,
00314                               &privk->u.dsa.params.prime);
00315            if (rv != SECSuccess) break;
00316            rv = SECITEM_CopyItem(arena, &pubk->u.dsa.params.subPrime,
00317                               &privk->u.dsa.params.subPrime);
00318            if (rv != SECSuccess) break;
00319            rv = SECITEM_CopyItem(arena, &pubk->u.dsa.params.base,
00320                               &privk->u.dsa.params.base);
00321            if (rv == SECSuccess) return pubk;
00322        }
00323        break;
00324       case NSSLOWKEYDHKey:
00325        pubk = (NSSLOWKEYPublicKey *)PORT_ArenaZAlloc(arena,
00326                                               sizeof(NSSLOWKEYPublicKey));
00327        if (pubk != NULL) {
00328            SECStatus rv;
00329 
00330            pubk->arena = arena;
00331            pubk->keyType = privk->keyType;
00332            rv = SECITEM_CopyItem(arena, &pubk->u.dh.publicValue,
00333                               &privk->u.dh.publicValue);
00334            if (rv != SECSuccess) break;
00335            rv = SECITEM_CopyItem(arena, &pubk->u.dh.prime,
00336                               &privk->u.dh.prime);
00337            if (rv != SECSuccess) break;
00338            rv = SECITEM_CopyItem(arena, &pubk->u.dh.base,
00339                               &privk->u.dh.base);
00340            if (rv == SECSuccess) return pubk;
00341        }
00342        break;
00343 #ifdef NSS_ENABLE_ECC
00344       case NSSLOWKEYECKey:
00345        pubk = (NSSLOWKEYPublicKey *)PORT_ArenaZAlloc(arena,
00346                                               sizeof(NSSLOWKEYPublicKey));
00347        if (pubk != NULL) {
00348            SECStatus rv;
00349 
00350            pubk->arena = arena;
00351            pubk->keyType = privk->keyType;
00352            rv = SECITEM_CopyItem(arena, &pubk->u.ec.publicValue,
00353                               &privk->u.ec.publicValue);
00354            if (rv != SECSuccess) break;
00355            pubk->u.ec.ecParams.arena = arena;
00356            /* Copy the rest of the params */
00357            rv = EC_CopyParams(arena, &(pubk->u.ec.ecParams),
00358                             &(privk->u.ec.ecParams));
00359            if (rv == SECSuccess) return pubk;
00360        }
00361        break;
00362 #endif /* NSS_ENABLE_ECC */
00363        /* No Fortezza in Low Key implementations (Fortezza keys aren't
00364         * stored in our data base */
00365     default:
00366        break;
00367     }
00368 
00369     PORT_FreeArena (arena, PR_FALSE);
00370     return NULL;
00371 }
00372 
00373 NSSLOWKEYPrivateKey *
00374 nsslowkey_CopyPrivateKey(NSSLOWKEYPrivateKey *privKey)
00375 {
00376     NSSLOWKEYPrivateKey *returnKey = NULL;
00377     SECStatus rv = SECFailure;
00378     PLArenaPool *poolp;
00379 
00380     if(!privKey) {
00381        return NULL;
00382     }
00383 
00384     poolp = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
00385     if(!poolp) {
00386        return NULL;
00387     }
00388 
00389     returnKey = (NSSLOWKEYPrivateKey*)PORT_ArenaZAlloc(poolp, sizeof(NSSLOWKEYPrivateKey));
00390     if(!returnKey) {
00391        rv = SECFailure;
00392        goto loser;
00393     }
00394 
00395     returnKey->keyType = privKey->keyType;
00396     returnKey->arena = poolp;
00397 
00398     switch(privKey->keyType) {
00399        case NSSLOWKEYRSAKey:
00400            rv = SECITEM_CopyItem(poolp, &(returnKey->u.rsa.modulus), 
00401                                    &(privKey->u.rsa.modulus));
00402            if(rv != SECSuccess) break;
00403            rv = SECITEM_CopyItem(poolp, &(returnKey->u.rsa.version), 
00404                                    &(privKey->u.rsa.version));
00405            if(rv != SECSuccess) break;
00406            rv = SECITEM_CopyItem(poolp, &(returnKey->u.rsa.publicExponent), 
00407                                    &(privKey->u.rsa.publicExponent));
00408            if(rv != SECSuccess) break;
00409            rv = SECITEM_CopyItem(poolp, &(returnKey->u.rsa.privateExponent), 
00410                                    &(privKey->u.rsa.privateExponent));
00411            if(rv != SECSuccess) break;
00412            rv = SECITEM_CopyItem(poolp, &(returnKey->u.rsa.prime1), 
00413                                    &(privKey->u.rsa.prime1));
00414            if(rv != SECSuccess) break;
00415            rv = SECITEM_CopyItem(poolp, &(returnKey->u.rsa.prime2), 
00416                                    &(privKey->u.rsa.prime2));
00417            if(rv != SECSuccess) break;
00418            rv = SECITEM_CopyItem(poolp, &(returnKey->u.rsa.exponent1), 
00419                                    &(privKey->u.rsa.exponent1));
00420            if(rv != SECSuccess) break;
00421            rv = SECITEM_CopyItem(poolp, &(returnKey->u.rsa.exponent2), 
00422                                    &(privKey->u.rsa.exponent2));
00423            if(rv != SECSuccess) break;
00424            rv = SECITEM_CopyItem(poolp, &(returnKey->u.rsa.coefficient), 
00425                                    &(privKey->u.rsa.coefficient));
00426            if(rv != SECSuccess) break;
00427            break;
00428        case NSSLOWKEYDSAKey:
00429            rv = SECITEM_CopyItem(poolp, &(returnKey->u.dsa.publicValue),
00430                                    &(privKey->u.dsa.publicValue));
00431            if(rv != SECSuccess) break;
00432            rv = SECITEM_CopyItem(poolp, &(returnKey->u.dsa.privateValue),
00433                                    &(privKey->u.dsa.privateValue));
00434            if(rv != SECSuccess) break;
00435            returnKey->u.dsa.params.arena = poolp;
00436            rv = SECITEM_CopyItem(poolp, &(returnKey->u.dsa.params.prime),
00437                                    &(privKey->u.dsa.params.prime));
00438            if(rv != SECSuccess) break;
00439            rv = SECITEM_CopyItem(poolp, &(returnKey->u.dsa.params.subPrime),
00440                                    &(privKey->u.dsa.params.subPrime));
00441            if(rv != SECSuccess) break;
00442            rv = SECITEM_CopyItem(poolp, &(returnKey->u.dsa.params.base),
00443                                    &(privKey->u.dsa.params.base));
00444            if(rv != SECSuccess) break;
00445            break;
00446        case NSSLOWKEYDHKey:
00447            rv = SECITEM_CopyItem(poolp, &(returnKey->u.dh.publicValue),
00448                                    &(privKey->u.dh.publicValue));
00449            if(rv != SECSuccess) break;
00450            rv = SECITEM_CopyItem(poolp, &(returnKey->u.dh.privateValue),
00451                                    &(privKey->u.dh.privateValue));
00452            if(rv != SECSuccess) break;
00453            returnKey->u.dsa.params.arena = poolp;
00454            rv = SECITEM_CopyItem(poolp, &(returnKey->u.dh.prime),
00455                                    &(privKey->u.dh.prime));
00456            if(rv != SECSuccess) break;
00457            rv = SECITEM_CopyItem(poolp, &(returnKey->u.dh.base),
00458                                    &(privKey->u.dh.base));
00459            if(rv != SECSuccess) break;
00460            break;
00461 #ifdef NSS_ENABLE_ECC
00462        case NSSLOWKEYECKey:
00463            rv = SECITEM_CopyItem(poolp, &(returnKey->u.ec.version),
00464                                    &(privKey->u.ec.version));
00465            if(rv != SECSuccess) break;
00466            rv = SECITEM_CopyItem(poolp, &(returnKey->u.ec.publicValue),
00467                                    &(privKey->u.ec.publicValue));
00468            if(rv != SECSuccess) break;
00469            rv = SECITEM_CopyItem(poolp, &(returnKey->u.ec.privateValue),
00470                                    &(privKey->u.ec.privateValue));
00471            if(rv != SECSuccess) break;
00472            returnKey->u.ec.ecParams.arena = poolp;
00473            /* Copy the rest of the params */
00474            rv = EC_CopyParams(poolp, &(returnKey->u.ec.ecParams),
00475                             &(privKey->u.ec.ecParams));
00476            if (rv != SECSuccess) break;
00477            break;
00478 #endif /* NSS_ENABLE_ECC */
00479        default:
00480            rv = SECFailure;
00481     }
00482 
00483 loser:
00484 
00485     if(rv != SECSuccess) {
00486        PORT_FreeArena(poolp, PR_TRUE);
00487        returnKey = NULL;
00488     }
00489 
00490     return returnKey;
00491 }