Exemple #1
0
int sign_value(pkcs11_handle_t *h, cert_object_t *cert, CK_BYTE *data,
	      CK_ULONG length, CK_BYTE **signature, CK_ULONG *signature_length)
{
  SECOidTag algtag;
  SECKEYPrivateKey *key;
  SECItem result;
  SECStatus rv;

  if (h->slot == NULL) {
    return -1;
  }

  /* get the key */
  key = PK11_FindPrivateKeyFromCert(h->slot, (CERTCertificate *)cert, NULL);
  if (key == NULL) {
    DBG1("Couldn't Find key for Cert: %s", SECU_Strerror(PR_GetError()));
    return -1;
  }

  /* get the oid */
  algtag = SEC_GetSignatureAlgorithmOidTag(key->keyType, SEC_OID_SHA1);

  /* sign the data */
  rv = SEC_SignData(&result, data, length, key, algtag);
  SECKEY_DestroyPrivateKey(key);
  if (rv != SECSuccess) {
    DBG1("Signature failed: %s", SECU_Strerror(PR_GetError()));
    return -1;
  }

  *signature = (CK_BYTE *)result.data;
  *signature_length = result.len;
  return 0;
}
Exemple #2
0
/* Create an ECDHE key pair for a given curve */
SECStatus
ssl_CreateECDHEphemeralKeyPair(const namedGroupDef *ecGroup,
                               sslEphemeralKeyPair **keyPair)
{
    SECKEYPrivateKey *privKey = NULL;
    SECKEYPublicKey *pubKey = NULL;
    SECKEYECParams ecParams = { siBuffer, NULL, 0 };
    sslEphemeralKeyPair *pair;

    if (ssl_NamedGroup2ECParams(NULL, ecGroup, &ecParams) != SECSuccess) {
        return SECFailure;
    }
    privKey = SECKEY_CreateECPrivateKey(&ecParams, &pubKey, NULL);
    SECITEM_FreeItem(&ecParams, PR_FALSE);

    if (!privKey || !pubKey ||
        !(pair = ssl_NewEphemeralKeyPair(ecGroup, privKey, pubKey))) {
        if (privKey) {
            SECKEY_DestroyPrivateKey(privKey);
        }
        if (pubKey) {
            SECKEY_DestroyPublicKey(pubKey);
        }
        ssl_MapLowLevelError(SEC_ERROR_KEYGEN_FAIL);
        return SECFailure;
    }

    *keyPair = pair;
    return SECSuccess;
}
Exemple #3
0
SECStatus
SSL_RestartHandshakeAfterChannelIDReq(PRFileDesc *      fd,
				      SECKEYPublicKey * channelIDPub,
				      SECKEYPrivateKey *channelID)
{
    sslSocket *   ss = ssl_FindSocket(fd);
    SECStatus     ret;

    if (!ss) {
	SSL_DBG(("%d: SSL[%d]: bad socket in"
		 " SSL_RestartHandshakeAfterChannelIDReq",
		 SSL_GETPID(), fd));
	goto loser;
    }


    ssl_Get1stHandshakeLock(ss);

    if (ss->version < SSL_LIBRARY_VERSION_3_0) {
	PORT_SetError(SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_SSL2);
	ssl_Release1stHandshakeLock(ss);
	goto loser;
    }

    ret = ssl3_RestartHandshakeAfterChannelIDReq(ss, channelIDPub,
						 channelID);
    ssl_Release1stHandshakeLock(ss);

    return ret;

loser:
    SECKEY_DestroyPublicKey(channelIDPub);
    SECKEY_DestroyPrivateKey(channelID);
    return SECFailure;
}
Exemple #4
0
char *oauth_sign_rsa_sha1 (const char *m, const char *k) {
  PK11SlotInfo      *slot = NULL;
  SECKEYPrivateKey  *pkey = NULL;
  SECItem            signature;
  SECStatus          s;
  SECItem            der;
  char              *rv=NULL;

  char *key = oauth_strip_pkcs(k, NS_PRIV_HEADER, NS_PRIV_TRAILER); 
  if (!key) return NULL;

  oauth_init_nss();

  slot = PK11_GetInternalKeySlot();
  if (!slot) goto looser;
  s = ATOB_ConvertAsciiToItem(&der, key);
  if (s != SECSuccess) goto looser;
  s = PK11_ImportDERPrivateKeyInfoAndReturnKey(slot, &der, NULL, NULL, PR_FALSE, PR_TRUE, KU_ALL, &pkey, NULL);
  SECITEM_FreeItem(&der, PR_FALSE);
  if (s != SECSuccess) goto looser;
  if (!pkey) goto looser;
  if (pkey->keyType != rsaKey) goto looser;
  s = SEC_SignData(&signature, (unsigned char*) m, strlen(m), pkey, SEC_OID_ISO_SHA1_WITH_RSA_SIGNATURE);
  if (s != SECSuccess) goto looser;

  rv=oauth_encode_base64(signature.len, signature.data);
  SECITEM_FreeItem(&signature, PR_FALSE);

looser:
  if (pkey) SECKEY_DestroyPrivateKey(pkey);
  if (slot) PK11_FreeSlot(slot);
  free(key);
  return rv;
}
/***********************************************************************
 *
 * J S S _ P K 1 1 _ w r a p P r i v K e y
 * privk: will be stored in a Java wrapper.
 * Returns: a new PK11PrivKey, or NULL if an exception occurred.
 */
jobject
JSS_PK11_wrapPrivKey(JNIEnv *env, SECKEYPrivateKey **privk)
{
	jclass keyClass;
	jmethodID constructor;
	jbyteArray ptrArray;
	jobject Key=NULL;
    const char *className = NULL;

	PR_ASSERT(env!=NULL && privk!=NULL && *privk!=NULL);

	/* Find the class */
    switch( (*privk)->keyType ) {
      case rsaKey:
        className = "org/mozilla/jss/pkcs11/PK11RSAPrivateKey";
        break;
      case dsaKey:
        className = "org/mozilla/jss/pkcs11/PK11DSAPrivateKey";
        break;
      case ecKey:
        className = "org/mozilla/jss/pkcs11/PK11ECPrivateKey";
        break;
      default:
        className = "org/mozilla/jss/pkcs11/PK11PrivKey";
        break;
    }
      
	keyClass = (*env)->FindClass(env, className);
	if(keyClass == NULL) {
		ASSERT_OUTOFMEM(env);
		goto finish;
	}

	/* find the constructor */
	constructor = (*env)->GetMethodID(env, keyClass, "<init>", "([B)V");
	if(constructor == NULL) {
		ASSERT_OUTOFMEM(env);
		goto finish;
	}

	/* convert the pointer to a byte array */
	ptrArray = JSS_ptrToByteArray(env, (void*)*privk);
	if(ptrArray == NULL) {
		goto finish;
	}
	/* call the constructor */
    Key = (*env)->NewObject(env, keyClass, constructor, ptrArray);

finish:
	if(Key == NULL) {
		SECKEY_DestroyPrivateKey(*privk);
	}
	*privk = NULL;
	return Key;
}
Exemple #6
0
int SslSocket::listen(const SocketAddress& sa, int backlog) const
{
    //get certificate and key (is this the correct way?)
    std::string cName( (certname == "") ? "localhost.localdomain" : certname);
    CERTCertificate *cert = PK11_FindCertFromNickname(const_cast<char*>(cName.c_str()), 0);
    if (!cert) throw Exception(QPID_MSG("Failed to load certificate '" << cName << "'"));
    SECKEYPrivateKey *key = PK11_FindKeyByAnyCert(cert, 0);
    if (!key) throw Exception(QPID_MSG("Failed to retrieve private key from certificate"));
    NSS_CHECK(SSL_ConfigSecureServer(prototype, cert, key, NSS_FindCertKEAType(cert)));
    SECKEY_DestroyPrivateKey(key);
    CERT_DestroyCertificate(cert);

    return BSDSocket::listen(sa, backlog);
}
Exemple #7
0
/**************************************************************************
 *
 * G e n e r a t e S e l f S i g n e d O b j e c t S i g n i n g C e r t
 *														   		  *phew*^
 *
 */
static CERTCertificate*
GenerateSelfSignedObjectSigningCert(char *nickname, CERTCertDBHandle *db,
 	char *subject, unsigned long serial, int keysize, char *token)
{
    CERTCertificate * cert, *temp_cert;
    SECItem * derCert;
    CERTCertificateRequest * req;

    PK11SlotInfo * slot = NULL;
    SECKEYPrivateKey * privk = NULL;
    SECKEYPublicKey * pubk = NULL;

    if ( token ) {
	slot = PK11_FindSlotByName(token);
    } else {
	slot = PK11_GetInternalKeySlot();
    }

    if (slot == NULL) {
	PR_fprintf(errorFD, "Can't find PKCS11 slot %s\n",
	    token ? token : "");
	errorCount++;
	exit (ERRX);
    }

    if ( GenerateKeyPair(slot, &pubk, &privk, keysize) != SECSuccess) {
	FatalError("Error generating keypair.");
    }
    req = make_cert_request (subject, pubk);
    temp_cert = make_cert (req, serial, &req->subject);
    if (set_cert_type(temp_cert,
        NS_CERT_TYPE_OBJECT_SIGNING | NS_CERT_TYPE_OBJECT_SIGNING_CA)
         != SECSuccess) {
	FatalError("Unable to set cert type");
    }

    derCert = sign_cert (temp_cert, privk);
    cert = install_cert(db, derCert, nickname);
    if (ChangeTrustAttributes(db, cert, ",,uC") != SECSuccess) {
	FatalError("Unable to change trust on generated certificate");
    }

    /* !!! Free memory ? !!! */
    PK11_FreeSlot(slot);
    SECKEY_DestroyPrivateKey(privk);
    SECKEY_DestroyPublicKey(pubk);

    return cert;
}
Exemple #8
0
/* Create an ECDHE key pair for a given curve */
SECStatus
ssl_CreateECDHEphemeralKeyPair(const sslSocket *ss,
                               const sslNamedGroupDef *ecGroup,
                               sslEphemeralKeyPair **keyPair)
{
    SECKEYPrivateKey *privKey = NULL;
    SECKEYPublicKey *pubKey = NULL;
    SECKEYECParams ecParams = { siBuffer, NULL, 0 };
    sslEphemeralKeyPair *pair;

    if (ssl_NamedGroup2ECParams(NULL, ecGroup, &ecParams) != SECSuccess) {
        return SECFailure;
    }
    privKey = SECKEY_CreateECPrivateKey(&ecParams, &pubKey, ss->pkcs11PinArg);
    SECITEM_FreeItem(&ecParams, PR_FALSE);

    if (!privKey || !pubKey ||
        !(pair = ssl_NewEphemeralKeyPair(ecGroup, privKey, pubKey))) {
        if (privKey) {
            SECKEY_DestroyPrivateKey(privKey);
        }
        if (pubKey) {
            SECKEY_DestroyPublicKey(pubKey);
        }
        ssl_MapLowLevelError(SEC_ERROR_KEYGEN_FAIL);
        return SECFailure;
    }

    *keyPair = pair;
    SSL_TRC(50, ("%d: SSL[%d]: Create ECDH ephemeral key %d",
                 SSL_GETPID(), ss ? ss->fd : NULL, ecGroup->name));
    PRINT_BUF(50, (ss, "Public Key", pubKey->u.ec.publicValue.data,
                   pubKey->u.ec.publicValue.len));
#ifdef TRACE
    if (ssl_trace >= 50) {
        SECItem d = { siBuffer, NULL, 0 };
        SECStatus rv = PK11_ReadRawAttribute(PK11_TypePrivKey, privKey,
                                             CKA_VALUE, &d);
        if (rv == SECSuccess) {
            PRINT_BUF(50, (ss, "Private Key", d.data, d.len));
            SECITEM_FreeItem(&d, PR_FALSE);
        } else {
            SSL_TRC(50, ("Error extracting private key"));
        }
    }
#endif
    return SECSuccess;
}
Exemple #9
0
/* Generate a key pair, and then generate a subjectPublicKeyInfo
** for the public key in that pair.  return all 3.
*/
CERTSubjectPublicKeyInfo *
GetSubjectPubKeyInfo(TESTKeyPair *pair)
{
    CERTSubjectPublicKeyInfo *spki       = NULL;
    SECKEYPrivateKey         *privKey    = NULL;
    SECKEYPublicKey          *pubKey     = NULL;
    PK11SlotInfo             *keySlot    = NULL;
    
    keySlot = PK11_GetInternalKeySlot();
    PK11_Authenticate(keySlot, PR_FALSE, &pwdata);


    if (!doingDSA) {
	PK11RSAGenParams *rsaParams = GetRSAParams();
	if (rsaParams == NULL) {
	    PK11_FreeSlot(keySlot);
	    return NULL;
	}
	privKey = PK11_GenerateKeyPair(keySlot, CKM_RSA_PKCS_KEY_PAIR_GEN,
				       (void*)rsaParams, &pubKey, PR_FALSE,
				       PR_FALSE, &pwdata);
    } else {
	PQGParams *dsaParams = GetDSAParams();
	if (dsaParams == NULL) {
	    PK11_FreeSlot(keySlot);
	    return NULL;
	}
	privKey = PK11_GenerateKeyPair(keySlot, CKM_DSA_KEY_PAIR_GEN,
				       (void*)dsaParams, &pubKey, PR_FALSE,
				       PR_FALSE, &pwdata);
    }
    PK11_FreeSlot(keySlot);
    if (privKey == NULL || pubKey == NULL) {
        if (pubKey) {
	    SECKEY_DestroyPublicKey(pubKey);
	}
	if (privKey) {
	    SECKEY_DestroyPrivateKey(privKey);
	}
	return NULL;
    }

    spki = SECKEY_CreateSubjectPublicKeyInfo(pubKey);
    pair->privKey = privKey;
    pair->pubKey  = pubKey;
    return spki;
}
Exemple #10
0
NSSCryptoKeyRSA::~NSSCryptoKeyRSA() {

  // Clean up

	if (mp_pubkey != 0)
		SECKEY_DestroyPublicKey(mp_pubkey);

  if (mp_privkey != 0)
		SECKEY_DestroyPrivateKey(mp_privkey);

	if (mp_modulus != NULL)
		 SECITEM_FreeItem(mp_modulus, PR_TRUE);

	if (mp_exponent != NULL)
		SECITEM_FreeItem(mp_exponent, PR_TRUE);

};
Exemple #11
0
/* destructor */
void
vcard_emul_delete_key(VCardKey *key)
{
    if (!nss_emul_init || (key == NULL)) {
        return;
    }
    if (key->key) {
        SECKEY_DestroyPrivateKey(key->key);
        key->key = NULL;
    }
    if (key->cert) {
        CERT_DestroyCertificate(key->cert);
    }
    if (key->slot) {
        PK11_FreeSlot(key->slot);
    }
}
void
nss_cms_recipient_list_destroy(NSSCMSRecipient **recipient_list)
{
    int i;
    NSSCMSRecipient *recipient;

    for (i=0; recipient_list[i] != NULL; i++) {
	recipient = recipient_list[i];
	if (recipient->cert)
	    CERT_DestroyCertificate(recipient->cert);
	if (recipient->privkey)
	    SECKEY_DestroyPrivateKey(recipient->privkey);
	if (recipient->slot)
	    PK11_FreeSlot(recipient->slot);
	PORT_Free(recipient);
    }
    PORT_Free(recipient_list);
}
Exemple #13
0
/*
 *  j a r _ f i n d _ k e y _ t y p e
 * 
 *  Determine the key type for a given cert, which 
 * should be rsaKey or dsaKey. Any error return 0.
 *
 */
static int	
jar_find_key_type (CERTCertificate *cert)
{
    SECKEYPrivateKey * privk = NULL;
    KeyType keyType;

    /* determine its type */
    privk = PK11_FindKeyByAnyCert (cert, &pwdata);
    if (privk == NULL) {
	PR_fprintf(errorFD, "warning - can't find private key for this cert\n");
	warningCount++;
	return 0;
    }

    keyType = privk->keyType;
    SECKEY_DestroyPrivateKey (privk);
    return keyType;
}
Exemple #14
0
/* nsIKeyPair createKeyPair(in PRUint32 aKeyType); */
NS_IMETHODIMP
KeyService::CreateKeyPair(PRUint32 aKeyType, nsIKeyPair **_retval)
{
    PK11RSAGenParams rsaparams;
    CK_MECHANISM_TYPE mechanism;
    void *params;

    // Initialize parameters based on key type
    switch (aKeyType) {
    case nsIKeyPair::KEYTYPE_RSA:
        rsaparams.keySizeInBits = 1024;
        rsaparams.pe = 0x010001;
        mechanism = CKM_RSA_PKCS_KEY_PAIR_GEN;
        params = &rsaparams;
        break;
    case nsIKeyPair::KEYTYPE_DSA:
        // Right now DSA can't be handled correctly
        return NS_ERROR_INVALID_ARG;
        mechanism = CKM_DSA_KEY_PAIR_GEN;
        params = (void *)&default_pqg_params;
        break;
    default:
        return NS_ERROR_INVALID_ARG;
    }
    
    // Create the key
    SECKEYPublicKey *pubKey;
    SECKEYPrivateKey *privKey;
    privKey = PK11_GenerateKeyPair(mSlot, mechanism, params, &pubKey, PR_TRUE, PR_TRUE, NULL);
    if (!privKey)
        return NS_ERROR_FAILURE;
    SECKEY_DestroyPublicKey(pubKey);

    // Pass on to a KeyPair
    KeyPair *key = new KeyPair(privKey);
    SECKEY_DestroyPrivateKey(privKey);
    if (!key)
        return NS_ERROR_OUT_OF_MEMORY;
    NS_ADDREF(*_retval = key);

    return NS_OK;
}
Exemple #15
0
/* This function adopts pubKey and destroys it if things go wrong. */
static sslKeyPair *
ssl_MakeKeyPairForCert(SECKEYPrivateKey *key, SECKEYPublicKey *pubKey)
{
    sslKeyPair *keyPair = NULL;
    SECKEYPrivateKey *privKeyCopy = NULL;
    PK11SlotInfo *bestSlot;

    if (key->pkcs11Slot) {
        bestSlot = PK11_ReferenceSlot(key->pkcs11Slot);
        if (bestSlot) {
            privKeyCopy = PK11_CopyTokenPrivKeyToSessionPrivKey(bestSlot, key);
            PK11_FreeSlot(bestSlot);
        }
    }
    if (!privKeyCopy) {
        CK_MECHANISM_TYPE keyMech = PK11_MapSignKeyType(key->keyType);
        /* XXX Maybe should be bestSlotMultiple? */
        bestSlot = PK11_GetBestSlot(keyMech, NULL /* wincx */);
        if (bestSlot) {
            privKeyCopy = PK11_CopyTokenPrivKeyToSessionPrivKey(bestSlot, key);
            PK11_FreeSlot(bestSlot);
        }
    }
    if (!privKeyCopy) {
        privKeyCopy = SECKEY_CopyPrivateKey(key);
    }
    if (privKeyCopy) {
        keyPair = ssl_NewKeyPair(privKeyCopy, pubKey);
    }
    if (!keyPair) {
        if (privKeyCopy) {
            SECKEY_DestroyPrivateKey(privKeyCopy);
        }
        /* We adopted the public key, so we're responsible. */
        if (pubKey) {
            SECKEY_DestroyPublicKey(pubKey);
        }
    }
    return keyPair;
}
Exemple #16
0
/*
 * attempt to restart the handshake after asynchronously handling
 * a request for the client's certificate.
 *
 * inputs:  
 *	cert	Client cert chosen by application.
 *		Note: ssl takes this reference, and does not bump the 
 *		reference count.  The caller should drop its reference
 *		without calling CERT_DestroyCertificate after calling this
 *		function.
 *
 *	key	Private key associated with cert.  This function takes
 *		ownership of the private key, so the caller should drop its
 *		reference without destroying the private key after this
 *		function returns.
 *
 *	certChain  Chain of signers for cert.  
 *		Note: ssl takes this reference, and does not copy the chain.
 *		The caller should drop its reference without destroying the 
 *		chain.  SSL will free the chain when it is done with it.
 *
 * Return value: XXX
 *
 * XXX This code only works on the initial handshake on a connection, XXX
 *     It does not work on a subsequent handshake (redo).
 */
SECStatus
SSL_RestartHandshakeAfterCertReq(PRFileDesc *        fd,
				CERTCertificate *    cert, 
				SECKEYPrivateKey *   key,
				CERTCertificateList *certChain)
{
    sslSocket *   ss = ssl_FindSocket(fd);
    SECStatus     ret;

    if (!ss) {
	SSL_DBG(("%d: SSL[%d]: bad socket in SSL_RestartHandshakeAfterCertReq",
		 SSL_GETPID(), fd));
	if (cert) {
	    CERT_DestroyCertificate(cert);
	}
	if (key) {
	    SECKEY_DestroyPrivateKey(key);
	}
	if (certChain) {
	    CERT_DestroyCertificateList(certChain);
	}
	return SECFailure;
    }

    ssl_Get1stHandshakeLock(ss);   /************************************/

    if (ss->version >= SSL_LIBRARY_VERSION_3_0) {
	ret = ssl3_RestartHandshakeAfterCertReq(ss, cert, key, certChain);
    } else {
	if (certChain != NULL) {
	    CERT_DestroyCertificateList(certChain);
	}
	PORT_SetError(SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_SSL2);
	ret = SECFailure;
    }

    ssl_Release1stHandshakeLock(ss);  /************************************/
    return ret;
}
Exemple #17
0
void
__pmSecureServerShutdown(void)
{
    PM_INIT_LOCKS();
    PM_LOCK(secureserver_lock);
    if (secure_server.certificate) {
	CERT_DestroyCertificate(secure_server.certificate);
	secure_server.certificate = NULL;
    }
    if (secure_server.private_key) {
	SECKEY_DestroyPrivateKey(secure_server.private_key);
	secure_server.private_key = NULL;
    }
    if (secure_server.ssl_session_cache_setup) {
	SSL_ShutdownServerSessionIDCache();
	secure_server.ssl_session_cache_setup = 0;
    }    
    if (secure_server.initialized) {
	NSS_Shutdown();
	secure_server.initialized = 0;
    }
    PM_UNLOCK(secureserver_lock);
}
Exemple #18
0
int SslSocket::listen(uint16_t port, int backlog, const std::string& certName, bool clientAuth) const
{
    //configure prototype socket:
    prototype = SSL_ImportFD(0, PR_NewTCPSocket());
    if (clientAuth) {
        NSS_CHECK(SSL_OptionSet(prototype, SSL_REQUEST_CERTIFICATE, PR_TRUE));
        NSS_CHECK(SSL_OptionSet(prototype, SSL_REQUIRE_CERTIFICATE, PR_TRUE));
    }

    //get certificate and key (is this the correct way?)
    CERTCertificate *cert = PK11_FindCertFromNickname(const_cast<char*>(certName.c_str()), 0);
    if (!cert) throw Exception(QPID_MSG("Failed to load certificate '" << certName << "'"));
    SECKEYPrivateKey *key = PK11_FindKeyByAnyCert(cert, 0);
    if (!key) throw Exception(QPID_MSG("Failed to retrieve private key from certificate"));
    NSS_CHECK(SSL_ConfigSecureServer(prototype, cert, key, NSS_FindCertKEAType(cert)));
    SECKEY_DestroyPrivateKey(key);
    CERT_DestroyCertificate(cert);

    //bind and listen
    const int& socket = impl->fd;
    int yes=1;
    QPID_POSIX_CHECK(setsockopt(socket,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(yes)));
    struct sockaddr_in name;
    name.sin_family = AF_INET;
    name.sin_port = htons(port);
    name.sin_addr.s_addr = 0;
    if (::bind(socket, (struct sockaddr*)&name, sizeof(name)) < 0)
        throw Exception(QPID_MSG("Can't bind to port " << port << ": " << strError(errno)));
    if (::listen(socket, backlog) < 0)
        throw Exception(QPID_MSG("Can't listen on port " << port << ": " << strError(errno)));
    
    socklen_t namelen = sizeof(name);
    if (::getsockname(socket, (struct sockaddr*)&name, &namelen) < 0)
        throw QPID_POSIX_ERROR(errno);

    return ntohs(name.sin_port);
}
Exemple #19
0
static xmlSecKeyPtr 
xmlSecNssKeysStoreFindKey(xmlSecKeyStorePtr store, const xmlChar* name, 
		          xmlSecKeyInfoCtxPtr keyInfoCtx) {
    xmlSecKeyStorePtr* ss;
    xmlSecKeyPtr key = NULL;
    xmlSecKeyPtr retval = NULL;
    xmlSecKeyReqPtr keyReq = NULL;
    CERTCertificate *cert = NULL;
    SECKEYPublicKey *pubkey = NULL;
    SECKEYPrivateKey *privkey = NULL;
    xmlSecKeyDataPtr data = NULL;
    xmlSecKeyDataPtr x509Data = NULL;
    int ret;

    xmlSecAssert2(xmlSecKeyStoreCheckId(store, xmlSecNssKeysStoreId), NULL);
    xmlSecAssert2(keyInfoCtx != NULL, NULL);

    ss = xmlSecNssKeysStoreGetSS(store);
    xmlSecAssert2(((ss != NULL) && (*ss != NULL)), NULL);

    key = xmlSecKeyStoreFindKey(*ss, name, keyInfoCtx);
    if (key != NULL) {
	return (key);
    }

    /* Try to find the key in the NSS DB, and construct an xmlSecKey.
     * we must have a name to lookup keys in NSS DB.
     */
    if (name == NULL) {
	goto done;
    }

    /* what type of key are we looking for? 
     * TBD: For now, we'll look only for public/private keys using the
     * name as a cert nickname. Later on, we can attempt to find
     * symmetric keys using PK11_FindFixedKey 
     */
    keyReq = &(keyInfoCtx->keyReq);
    if (keyReq->keyType & 
	(xmlSecKeyDataTypePublic | xmlSecKeyDataTypePrivate)) {
	cert = CERT_FindCertByNickname (CERT_GetDefaultCertDB(), (char *)name);
	if (cert == NULL) {
	    goto done;
	}

	if (keyReq->keyType & xmlSecKeyDataTypePublic) {
 	    pubkey = CERT_ExtractPublicKey(cert);
	    if (pubkey == NULL) {
		xmlSecErr_a_ignorar5(XMLSEC_ERRORS_HERE,
			    NULL,
			    "CERT_ExtractPublicKey",
			    XMLSEC_ERRORS_R_CRYPTO_FAILED,
			    XMLSEC_ERRORS_NO_MESSAGE);
		goto done;
	    }
	} 

	if (keyReq->keyType & xmlSecKeyDataTypePrivate) { 
 	    privkey = PK11_FindKeyByAnyCert(cert, NULL);
	    if (privkey == NULL) {
		xmlSecErr_a_ignorar5(XMLSEC_ERRORS_HERE,
			    NULL,
			    "PK11_FindKeyByAnyCert",
			    XMLSEC_ERRORS_R_CRYPTO_FAILED,
			    XMLSEC_ERRORS_NO_MESSAGE);
		goto done;
	    }
	}

	data = xmlSecNssPKIAdoptKey(privkey, pubkey);
	if(data == NULL) {
	    xmlSecErr_a_ignorar5(XMLSEC_ERRORS_HERE,
			NULL,
			"xmlSecNssPKIAdoptKey",
			XMLSEC_ERRORS_R_XMLSEC_FAILED,
			XMLSEC_ERRORS_NO_MESSAGE);
	    goto done;
	}    
	privkey = NULL;
	pubkey = NULL;

        key = xmlSecKeyCreate();
        if (key == NULL) {
	    xmlSecErr_a_ignorar5(XMLSEC_ERRORS_HERE,
			NULL,
			"xmlSecKeyCreate",
			XMLSEC_ERRORS_R_XMLSEC_FAILED,
			XMLSEC_ERRORS_NO_MESSAGE);
	    return (NULL);
        }

	x509Data = xmlSecKeyDataCreate(xmlSecNssKeyDataX509Id);
	if(x509Data == NULL) {
	    xmlSecErr_a_ignorar6(XMLSEC_ERRORS_HERE,
			NULL,
			"xmlSecKeyDataCreate",
			XMLSEC_ERRORS_R_XMLSEC_FAILED,
			"transform=%s",
			xmlSecErrorsSafeString(xmlSecTransformKlassGetName(xmlSecNssKeyDataX509Id)));
	    goto done;
	}

	ret = xmlSecNssKeyDataX509AdoptKeyCert(x509Data, cert);
	if (ret < 0) {
	    xmlSecErr_a_ignorar6(XMLSEC_ERRORS_HERE,
			NULL,
			"xmlSecNssKeyDataX509AdoptKeyCert",
			XMLSEC_ERRORS_R_XMLSEC_FAILED,
			"data=%s",
			xmlSecErrorsSafeString(xmlSecKeyDataGetName(x509Data)));
	    goto done;
	}
	cert = CERT_DupCertificate(cert);
	if (cert == NULL) {
	    xmlSecErr_a_ignorar6(XMLSEC_ERRORS_HERE,
			NULL,
			"CERT_DupCertificate",
			XMLSEC_ERRORS_R_CRYPTO_FAILED,
			"data=%s",
			xmlSecErrorsSafeString(xmlSecKeyDataGetName(x509Data)));
	    goto done;
	}

	ret = xmlSecNssKeyDataX509AdoptCert(x509Data, cert);
	if (ret < 0) {
	    xmlSecErr_a_ignorar6(XMLSEC_ERRORS_HERE,
			NULL,
			"xmlSecNssKeyDataX509AdoptCert",
			XMLSEC_ERRORS_R_XMLSEC_FAILED,
			"data=%s",
			xmlSecErrorsSafeString(xmlSecKeyDataGetName(x509Data)));
	    goto done;
	}
	cert = NULL;

	ret = xmlSecKeySetValue(key, data);
	if (ret < 0) {
	    xmlSecErr_a_ignorar6(XMLSEC_ERRORS_HERE,
			NULL,
			"xmlSecKeySetValue",
			XMLSEC_ERRORS_R_XMLSEC_FAILED,
			"data=%s", 
			xmlSecErrorsSafeString(xmlSecKeyDataGetName(data)));
	    goto done;
	}
	data = NULL;

	ret = xmlSecKeyAdoptData(key, x509Data);
	if (ret < 0) {
	    xmlSecErr_a_ignorar6(XMLSEC_ERRORS_HERE,
			NULL,
			"xmlSecKeyAdoptData",
			XMLSEC_ERRORS_R_XMLSEC_FAILED,
			"data=%s",
			xmlSecErrorsSafeString(xmlSecKeyDataGetName(x509Data)));
	    goto done;
	}
	x509Data = NULL;

	retval = key;
	key = NULL;
    }

done:
    if (cert != NULL) {
	CERT_DestroyCertificate(cert);
    }
    if (pubkey != NULL) {
	SECKEY_DestroyPublicKey(pubkey);
    }
    if (privkey != NULL) {
	SECKEY_DestroyPrivateKey(privkey);
    }
    if (data != NULL) {
	xmlSecKeyDataDestroy(data);
    }
    if (x509Data != NULL) {
	xmlSecKeyDataDestroy(x509Data);
    }
    if (key != NULL) {
	xmlSecKeyDestroy(key);
    }

    return (retval);
}
Exemple #20
0
/*
 * generate an RSA signature key
 *
 * e is fixed at 3, without discussion.  That would not be wise if these
 * keys were to be used for encryption, but for signatures there are some
 * real speed advantages.
 * See also: https://www.imperialviolet.org/2012/03/16/rsae.html
 */
void rsasigkey(int nbits, int seedbits, const struct lsw_conf_options *oco)
{
	PK11RSAGenParams rsaparams = { nbits, (long) F4 };
	PK11SlotInfo *slot = NULL;
	SECKEYPrivateKey *privkey = NULL;
	SECKEYPublicKey *pubkey = NULL;
	realtime_t now = realnow();

	lsw_nss_buf_t err;
	if (!lsw_nss_setup(oco->nssdir, 0, lsw_nss_get_password, err)) {
		fprintf(stderr, "%s: %s\n", progname, err);
		exit(1);
	}

#ifdef FIPS_CHECK
	if (PK11_IsFIPS() && !FIPSCHECK_verify(NULL, NULL)) {
		fprintf(stderr,
			"FIPS HMAC integrity verification test failed.\n");
		exit(1);
	}
#endif

	/* Good for now but someone may want to use a hardware token */
	slot = lsw_nss_get_authenticated_slot(err);
	if (slot == NULL) {
		fprintf(stderr, "%s: %s\n", progname, err);
		lsw_nss_shutdown();
		exit(1);
	}

	/* Do some random-number initialization. */
	UpdateNSS_RNG(seedbits);
	privkey = PK11_GenerateKeyPair(slot,
				       CKM_RSA_PKCS_KEY_PAIR_GEN,
				       &rsaparams, &pubkey,
				       PR_TRUE,
				       PK11_IsFIPS() ? PR_TRUE : PR_FALSE,
				       lsw_return_nss_password_file_info());
	/* inTheToken, isSensitive, passwordCallbackFunction */
	if (privkey == NULL) {
		fprintf(stderr,
			"%s: key pair generation failed: \"%d\"\n", progname,
			PORT_GetError());
		return;
	}

	chunk_t public_modulus = {
		.ptr = pubkey->u.rsa.modulus.data,
		.len = pubkey->u.rsa.modulus.len,
	};
	chunk_t public_exponent = {
		.ptr = pubkey->u.rsa.publicExponent.data,
		.len = pubkey->u.rsa.publicExponent.len,
	};

	char *hex_ckaid;
	{
		SECItem *ckaid = PK11_GetLowLevelKeyIDForPrivateKey(privkey);
		if (ckaid == NULL) {
			fprintf(stderr, "%s: 'CKAID' calculation failed\n", progname);
			exit(1);
		}
		hex_ckaid = strdup(conv(ckaid->data, ckaid->len, 16));
		SECITEM_FreeItem(ckaid, PR_TRUE);
	}

	/*privkey->wincx = &pwdata;*/
	PORT_Assert(pubkey != NULL);
	fprintf(stderr, "Generated RSA key pair with CKAID %s was stored in the NSS database\n",
		hex_ckaid);

	/* and the output */
	libreswan_log("output...\n");  /* deliberate extra newline */
	printf("\t# RSA %d bits   %s   %s", nbits, outputhostname,
		ctime(&now.rt.tv_sec));
	/* ctime provides \n */
	printf("\t# for signatures only, UNSAFE FOR ENCRYPTION\n");

	printf("\t#ckaid=%s\n", hex_ckaid);

	/* RFC2537/RFC3110-ish format */
	{
		char *base64 = NULL;
		err_t err = rsa_pubkey_to_base64(public_exponent, public_modulus, &base64);
		if (err) {
			fprintf(stderr, "%s: unexpected error encoding RSA public key '%s'\n",
				progname, err);
			exit(1);
		}
		printf("\t#pubkey=%s\n", base64);
		pfree(base64);
	}

	printf("\tModulus: 0x%s\n", conv(public_modulus.ptr, public_modulus.len, 16));
	printf("\tPublicExponent: 0x%s\n", conv(public_exponent.ptr, public_exponent.len, 16));

	if (hex_ckaid != NULL)
		free(hex_ckaid);
	if (privkey != NULL)
		SECKEY_DestroyPrivateKey(privkey);
	if (pubkey != NULL)
		SECKEY_DestroyPublicKey(pubkey);

	lsw_nss_shutdown();
}

/*
 * lsw_random - get some random bytes from /dev/random (or wherever)
 * NOTE: This is only used for additional seeding of the NSS RNG
 */
void lsw_random(size_t nbytes, unsigned char *buf)
{
	size_t ndone;
	int dev;
	ssize_t got;

	dev = open(device, 0);
	if (dev < 0) {
		fprintf(stderr, "%s: could not open %s (%s)\n", progname,
			device, strerror(errno));
		exit(1);
	}

	ndone = 0;
	libreswan_log("getting %d random seed bytes for NSS from %s...\n",
		      (int) nbytes * BITS_PER_BYTE, device);
	while (ndone < nbytes) {
		got = read(dev, buf + ndone, nbytes - ndone);
		if (got < 0) {
			fprintf(stderr, "%s: read error on %s (%s)\n", progname,
				device, strerror(errno));
			exit(1);
		}
		if (got == 0) {
			fprintf(stderr, "%s: eof on %s!?!\n", progname, device);
			exit(1);
		}
		ndone += got;
	}

	close(dev);
}

/*
   - conv - convert bits to output in specified datatot format
 * NOTE: result points into a STATIC buffer
 */
static const char *conv(const unsigned char *bits, size_t nbytes, int format)
{
	static char convbuf[MAXBITS / 4 + 50];  /* enough for hex */
	size_t n;

	n = datatot(bits, nbytes, format, convbuf, sizeof(convbuf));
	if (n == 0) {
		fprintf(stderr, "%s: can't-happen convert error\n", progname);
		exit(1);
	}
	if (n > sizeof(convbuf)) {
		fprintf(stderr,
			"%s: can't-happen convert overflow (need %d)\n",
			progname, (int) n);
		exit(1);
	}
	return convbuf;
}
Exemple #21
0
/* Called from ssl3_SendClientKeyExchange(). */
SECStatus
ssl3_SendECDHClientKeyExchange(sslSocket * ss, SECKEYPublicKey * svrPubKey)
{
    PK11SymKey *	pms 		= NULL;
    SECStatus           rv    		= SECFailure;
    PRBool              isTLS, isTLS12;
    CK_MECHANISM_TYPE	target;
    SECKEYPublicKey	*pubKey = NULL;		/* Ephemeral ECDH key */
    SECKEYPrivateKey	*privKey = NULL;	/* Ephemeral ECDH key */

    PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss) );
    PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss));

    isTLS = (PRBool)(ss->ssl3.pwSpec->version > SSL_LIBRARY_VERSION_3_0);
    isTLS12 = (PRBool)(ss->ssl3.pwSpec->version >= SSL_LIBRARY_VERSION_TLS_1_2);

    /* Generate ephemeral EC keypair */
    if (svrPubKey->keyType != ecKey) {
	PORT_SetError(SEC_ERROR_BAD_KEY);
	goto loser;
    }
    /* XXX SHOULD CALL ssl3_CreateECDHEphemeralKeys here, instead! */
    privKey = SECKEY_CreateECPrivateKey(&svrPubKey->u.ec.DEREncodedParams, 
	                                &pubKey, ss->pkcs11PinArg);
    if (!privKey || !pubKey) {
	    ssl_MapLowLevelError(SEC_ERROR_KEYGEN_FAIL);
	    rv = SECFailure;
	    goto loser;
    }
    PRINT_BUF(50, (ss, "ECDH public value:",
					pubKey->u.ec.publicValue.data,
					pubKey->u.ec.publicValue.len));

    if (isTLS12) {
	target = CKM_NSS_TLS_MASTER_KEY_DERIVE_DH_SHA256;
    } else if (isTLS) {
	target = CKM_TLS_MASTER_KEY_DERIVE_DH;
    } else {
	target = CKM_SSL3_MASTER_KEY_DERIVE_DH;
    }

    /*  Determine the PMS */
    pms = PK11_PubDeriveWithKDF(privKey, svrPubKey, PR_FALSE, NULL, NULL,
			    CKM_ECDH1_DERIVE, target, CKA_DERIVE, 0,
			    CKD_NULL, NULL, NULL);

    if (pms == NULL) {
	SSL3AlertDescription desc  = illegal_parameter;
	(void)SSL3_SendAlert(ss, alert_fatal, desc);
	ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE);
	goto loser;
    }

    SECKEY_DestroyPrivateKey(privKey);
    privKey = NULL;

    rv = ssl3_InitPendingCipherSpec(ss,  pms);
    PK11_FreeSymKey(pms); pms = NULL;

    if (rv != SECSuccess) {
	ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE);
	goto loser;
    }

    rv = ssl3_AppendHandshakeHeader(ss, client_key_exchange, 
					pubKey->u.ec.publicValue.len + 1);
    if (rv != SECSuccess) {
        goto loser;	/* err set by ssl3_AppendHandshake* */
    }

    rv = ssl3_AppendHandshakeVariable(ss, 
					pubKey->u.ec.publicValue.data,
					pubKey->u.ec.publicValue.len, 1);
    SECKEY_DestroyPublicKey(pubKey);
    pubKey = NULL;

    if (rv != SECSuccess) {
        goto loser;	/* err set by ssl3_AppendHandshake* */
    }

    rv = SECSuccess;

loser:
    if(pms) PK11_FreeSymKey(pms);
    if(privKey) SECKEY_DestroyPrivateKey(privKey);
    if(pubKey) SECKEY_DestroyPublicKey(pubKey);
    return rv;
}
Exemple #22
0
nsresult
nsKeygenFormProcessor::GetPublicKey(const nsAString& aValue,
                                    const nsAString& aChallenge,
                                    const nsAFlatString& aKeyType,
                                    nsAString& aOutPublicKey,
                                    const nsAString& aKeyParams)
{
    nsNSSShutDownPreventionLock locker;
    if (isAlreadyShutDown()) {
      return NS_ERROR_NOT_AVAILABLE;
    }

    nsresult rv = NS_ERROR_FAILURE;
    char *keystring = nullptr;
    char *keyparamsString = nullptr;
    uint32_t keyGenMechanism;
    PK11SlotInfo *slot = nullptr;
    PK11RSAGenParams rsaParams;
    SECOidTag algTag;
    int keysize = 0;
    void *params = nullptr;
    SECKEYPrivateKey *privateKey = nullptr;
    SECKEYPublicKey *publicKey = nullptr;
    CERTSubjectPublicKeyInfo *spkInfo = nullptr;
    SECStatus srv = SECFailure;
    SECItem spkiItem;
    SECItem pkacItem;
    SECItem signedItem;
    CERTPublicKeyAndChallenge pkac;
    pkac.challenge.data = nullptr;
    nsIGeneratingKeypairInfoDialogs * dialogs;
    nsKeygenThread *KeygenRunnable = 0;
    nsCOMPtr<nsIKeygenThread> runnable;

    // permanent and sensitive flags for keygen
    PK11AttrFlags attrFlags = PK11_ATTR_TOKEN | PK11_ATTR_SENSITIVE | PK11_ATTR_PRIVATE;

    UniquePLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE));
    if (!arena) {
        goto loser;
    }

    // Get the key size //
    for (size_t i = 0; i < number_of_key_size_choices; ++i) {
        if (aValue.Equals(mSECKeySizeChoiceList[i].name)) {
            keysize = mSECKeySizeChoiceList[i].size;
            break;
        }
    }
    if (!keysize) {
        goto loser;
    }

    // Set the keygen mechanism
    if (aKeyType.IsEmpty() || aKeyType.LowerCaseEqualsLiteral("rsa")) {
        keyGenMechanism = CKM_RSA_PKCS_KEY_PAIR_GEN;
    } else if (aKeyType.LowerCaseEqualsLiteral("ec")) {
        keyparamsString = ToNewCString(aKeyParams);
        if (!keyparamsString) {
            rv = NS_ERROR_OUT_OF_MEMORY;
            goto loser;
        }

        keyGenMechanism = CKM_EC_KEY_PAIR_GEN;
        /* ecParams are initialized later */
    } else {
        goto loser;
    }

    // Get the slot
    rv = GetSlot(keyGenMechanism, &slot);
    if (NS_FAILED(rv)) {
        goto loser;
    }
    switch (keyGenMechanism) {
        case CKM_RSA_PKCS_KEY_PAIR_GEN:
            rsaParams.keySizeInBits = keysize;
            rsaParams.pe = DEFAULT_RSA_KEYGEN_PE;
            algTag = DEFAULT_RSA_KEYGEN_ALG;
            params = &rsaParams;
            break;
        case CKM_EC_KEY_PAIR_GEN:
            /* XXX We ought to rethink how the KEYGEN tag is 
             * displayed. The pulldown selections presented
             * to the user must depend on the keytype.
             * The displayed selection could be picked
             * from the keyparams attribute (this is currently called
             * the pqg attribute).
             * For now, we pick ecparams from the keyparams field
             * if it specifies a valid supported curve, or else 
             * we pick one of secp384r1, secp256r1 or secp192r1
             * respectively depending on the user's selection
             * (High, Medium, Low). 
             * (RSA uses RSA-2048, RSA-1024 and RSA-512 for historical
             * reasons, while ECC choices represent a stronger mapping)
             * NOTE: The user's selection
             * is silently ignored when a valid curve is presented
             * in keyparams.
             */
            if ((params = decode_ec_params(keyparamsString)) == nullptr) {
                /* The keyparams attribute did not specify a valid
                 * curve name so use a curve based on the keysize.
                 * NOTE: Here keysize is used only as an indication of
                 * High/Medium/Low strength; elliptic curve
                 * cryptography uses smaller keys than RSA to provide
                 * equivalent security.
                 */
                switch (keysize) {
                case 2048:
                    params = decode_ec_params("secp384r1");
                    break;
                case 1024:
                case 512:
                    params = decode_ec_params("secp256r1");
                    break;
                } 
            }
            /* XXX The signature algorithm ought to choose the hashing
             * algorithm based on key size once ECDSA variations based
             * on SHA256 SHA384 and SHA512 are standardized.
             */
            algTag = SEC_OID_ANSIX962_ECDSA_SIGNATURE_WITH_SHA1_DIGEST;
            break;
      default:
          goto loser;
      }

    /* Make sure token is initialized. */
    rv = setPassword(slot, m_ctx, locker);
    if (NS_FAILED(rv))
        goto loser;

    srv = PK11_Authenticate(slot, true, m_ctx);
    if (srv != SECSuccess) {
        goto loser;
    }

    rv = getNSSDialogs((void**)&dialogs,
                       NS_GET_IID(nsIGeneratingKeypairInfoDialogs),
                       NS_GENERATINGKEYPAIRINFODIALOGS_CONTRACTID);

    if (NS_SUCCEEDED(rv)) {
        KeygenRunnable = new nsKeygenThread();
        NS_IF_ADDREF(KeygenRunnable);
    }

    if (NS_FAILED(rv) || !KeygenRunnable) {
        rv = NS_OK;
        privateKey = PK11_GenerateKeyPairWithFlags(slot, keyGenMechanism, params,
                                                   &publicKey, attrFlags, m_ctx);
    } else {
        KeygenRunnable->SetParams( slot, attrFlags, nullptr, 0,
                                   keyGenMechanism, params, m_ctx );

        runnable = do_QueryInterface(KeygenRunnable);
        
        if (runnable) {
            rv = dialogs->DisplayGeneratingKeypairInfo(m_ctx, runnable);
            // We call join on the thread so we can be sure that no
            // simultaneous access to the passed parameters will happen.
            KeygenRunnable->Join();

            NS_RELEASE(dialogs);
            if (NS_SUCCEEDED(rv)) {
                PK11SlotInfo *used_slot = nullptr;
                rv = KeygenRunnable->ConsumeResult(&used_slot, &privateKey, &publicKey);
                if (NS_SUCCEEDED(rv) && used_slot) {
                  PK11_FreeSlot(used_slot);
                }
            }
        }
    }
    
    if (NS_FAILED(rv) || !privateKey) {
        goto loser;
    }
    // just in case we'll need to authenticate to the db -jp //
    privateKey->wincx = m_ctx;

    /*
     * Create a subject public key info from the public key.
     */
    spkInfo = SECKEY_CreateSubjectPublicKeyInfo(publicKey);
    if ( !spkInfo ) {
        goto loser;
    }

    /*
     * Now DER encode the whole subjectPublicKeyInfo.
     */
    srv = DER_Encode(arena.get(), &spkiItem, CERTSubjectPublicKeyInfoTemplate,
                     spkInfo);
    if (srv != SECSuccess) {
        goto loser;
    }

    /*
     * set up the PublicKeyAndChallenge data structure, then DER encode it
     */
    pkac.spki = spkiItem;
    pkac.challenge.len = aChallenge.Length();
    pkac.challenge.data = (unsigned char *)ToNewCString(aChallenge);
    if (!pkac.challenge.data) {
        rv = NS_ERROR_OUT_OF_MEMORY;
        goto loser;
    }

    srv = DER_Encode(arena.get(), &pkacItem, CERTPublicKeyAndChallengeTemplate,
                     &pkac);
    if (srv != SECSuccess) {
        goto loser;
    }

    /*
     * now sign the DER encoded PublicKeyAndChallenge
     */
    srv = SEC_DerSignData(arena.get(), &signedItem, pkacItem.data, pkacItem.len,
                          privateKey, algTag);
    if (srv != SECSuccess) {
        goto loser;
    }

    /*
     * Convert the signed public key and challenge into base64/ascii.
     */
    keystring = BTOA_DataToAscii(signedItem.data, signedItem.len);
    if (!keystring) {
        rv = NS_ERROR_OUT_OF_MEMORY;
        goto loser;
    }

    CopyASCIItoUTF16(keystring, aOutPublicKey);
    free(keystring);

    rv = NS_OK;

    GatherKeygenTelemetry(keyGenMechanism, keysize, keyparamsString);
loser:
    if (srv != SECSuccess) {
        if ( privateKey ) {
            PK11_DestroyTokenObject(privateKey->pkcs11Slot,privateKey->pkcs11ID);
        }
        if ( publicKey ) {
            PK11_DestroyTokenObject(publicKey->pkcs11Slot,publicKey->pkcs11ID);
        }
    }
    if ( spkInfo ) {
        SECKEY_DestroySubjectPublicKeyInfo(spkInfo);
    }
    if ( publicKey ) {
        SECKEY_DestroyPublicKey(publicKey);
    }
    if ( privateKey ) {
        SECKEY_DestroyPrivateKey(privateKey);
    }
    if (slot) {
        PK11_FreeSlot(slot);
    }
    if (KeygenRunnable) {
        NS_RELEASE(KeygenRunnable);
    }
    if (keyparamsString) {
        free(keyparamsString);
    }
    if (pkac.challenge.data) {
        free(pkac.challenge.data);
    }
    // If params is non-null and doesn't point to rsaParams, it was allocated
    // in decode_ec_params. We have to free this memory.
    if (params && params != &rsaParams) {
        SECITEM_FreeItem(static_cast<SECItem*>(params), true);
        params = nullptr;
    }
    return rv;
}
Exemple #23
0
SECStatus
SSL_ConfigSecureServerWithCertChain(PRFileDesc *fd, CERTCertificate *cert,
                                    const CERTCertificateList *certChainOpt,
                                    SECKEYPrivateKey *key, SSL3KEAType kea)
{
    sslSocket *ss;
    SECKEYPublicKey *pubKey = NULL;
    ssl3KeyPair *keyPair = NULL;
    SECStatus rv = SECFailure;

    ss = ssl_FindSocket(fd);
    if (!ss) {
	return SECFailure;
    }

    /* Both key and cert must have a value or be NULL */
    /* Passing a value of NULL will turn off key exchange algorithms that were
     * previously turned on */
    if (!cert != !key) {
	PORT_SetError(SEC_ERROR_INVALID_ARGS);
	return SECFailure;
    }

    /* make sure the key exchange is recognized */
    if ((kea >= kt_kea_size) || (kea < kt_null)) {
	PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG);
	return SECFailure;
    }

    if (kea != NSS_FindCertKEAType(cert)) {
    	PORT_SetError(SSL_ERROR_CERT_KEA_MISMATCH);
	return SECFailure;
    }

    if (cert) {
    	/* get the size of the cert's public key, and remember it */
	pubKey = CERT_ExtractPublicKey(cert);
	if (!pubKey) 
            return SECFailure;
    }

    if (key) {
	SECKEYPrivateKey * keyCopy	= NULL;
	CK_MECHANISM_TYPE  keyMech	= CKM_INVALID_MECHANISM;

	if (key->pkcs11Slot) {
	    PK11SlotInfo * bestSlot;
	    bestSlot = PK11_ReferenceSlot(key->pkcs11Slot);
	    if (bestSlot) {
		keyCopy = PK11_CopyTokenPrivKeyToSessionPrivKey(bestSlot, key);
		PK11_FreeSlot(bestSlot);
	    }
	}
	if (keyCopy == NULL)
	    keyMech = PK11_MapSignKeyType(key->keyType);
	if (keyMech != CKM_INVALID_MECHANISM) {
	    PK11SlotInfo * bestSlot;
	    /* XXX Maybe should be bestSlotMultiple? */
	    bestSlot = PK11_GetBestSlot(keyMech, NULL /* wincx */);
	    if (bestSlot) {
		keyCopy = PK11_CopyTokenPrivKeyToSessionPrivKey(bestSlot, key);
		PK11_FreeSlot(bestSlot);
	    }
	}
	if (keyCopy == NULL)
	    keyCopy = SECKEY_CopyPrivateKey(key);
	if (keyCopy == NULL)
	    goto loser;
        keyPair = ssl3_NewKeyPair(keyCopy, pubKey);
        if (keyPair == NULL) {
            SECKEY_DestroyPrivateKey(keyCopy);
            goto loser;
        }
	pubKey = NULL; /* adopted by serverKeyPair */
    }
    if (ssl_ConfigSecureServer(ss, cert, certChainOpt,
                               keyPair, kea) == SECFailure) {
        goto loser;
    }

    /* Only do this once because it's global. */
    if (PR_SUCCESS == PR_CallOnceWithArg(&setupServerCAListOnce, 
                                         &serverCAListSetup,
                                         (void *)(ss->dbHandle))) {
        rv = SECSuccess;
    }

loser:
    if (keyPair) {
        ssl3_FreeKeyPair(keyPair);
    }
    if (pubKey) {
	SECKEY_DestroyPublicKey(pubKey); 
	pubKey = NULL;
    }
    return rv;
}
Exemple #24
0
/* here we are just freeing RAM */
void free_state(struct state *st)
{
    delete_event(st);	/* delete any pending timer event */

    {
	struct msgid_list *p = st->st_used_msgids;

	while (p != NULL)
	{
	    struct msgid_list *q = p;
	    p = p->next;
	    pfree(q);
	}
    }

    unreference_key(&st->st_peer_pubkey);

    free_sa(st->st_sadb);
    st->st_sadb=NULL;

    if (st->st_sec_in_use) {
#ifdef HAVE_LIBNSS
	SECKEYPrivateKey *privk;
	SECKEYPublicKey   *pubk;
	memcpy(&pubk,st->pubk.ptr,st->pubk.len);
	SECKEY_DestroyPublicKey(pubk);
	freeanychunk(st->pubk);
	memcpy(&privk,st->st_sec_chunk.ptr,st->st_sec_chunk.len);
	SECKEY_DestroyPrivateKey(privk);
#else
	mpz_clear(&(st->st_sec));
#endif
	pfreeany(st->st_sec_chunk.ptr);
    }

    freeanychunk(st->st_firstpacket_me);
    freeanychunk(st->st_firstpacket_him);
    freeanychunk(st->st_tpacket);
    freeanychunk(st->st_rpacket);
    freeanychunk(st->st_p1isa);
    freeanychunk(st->st_gi);
    freeanychunk(st->st_gr);
    freeanychunk(st->st_shared);
    freeanychunk(st->st_ni);
    freeanychunk(st->st_nr);
#ifdef HAVE_LIBNSS
    free_osw_nss_symkey(st->st_skeyid);
    free_osw_nss_symkey(st->st_skey_d);
    free_osw_nss_symkey(st->st_skey_ai);
    free_osw_nss_symkey(st->st_skey_ar);
    free_osw_nss_symkey(st->st_skey_ei);
    free_osw_nss_symkey(st->st_skey_er);
    free_osw_nss_symkey(st->st_skey_pi);
    free_osw_nss_symkey(st->st_skey_pr);
    free_osw_nss_symkey(st->st_enc_key);

    if(st->st_ah.our_keymat!=NULL)
    memset(st->st_ah.our_keymat, 0, st->st_ah.keymat_len);

    if(st->st_ah.peer_keymat!=NULL)
    memset(st->st_ah.peer_keymat, 0, st->st_ah.keymat_len);

    if(st->st_esp.our_keymat!=NULL)
    memset(st->st_esp.our_keymat, 0, st->st_esp.keymat_len);

    if(st->st_esp.peer_keymat!=NULL)
    memset(st->st_esp.peer_keymat, 0, st->st_esp.keymat_len);
#endif
    freeanychunk(st->st_skeyid);
    freeanychunk(st->st_skey_d);
    freeanychunk(st->st_skey_ai);
    freeanychunk(st->st_skey_ar);
    freeanychunk(st->st_skey_ei);
    freeanychunk(st->st_skey_er);
    freeanychunk(st->st_skey_pi);
    freeanychunk(st->st_skey_pr);
    freeanychunk(st->st_enc_key);
    pfreeany(st->st_ah.our_keymat);
    pfreeany(st->st_ah.peer_keymat);
    pfreeany(st->st_esp.our_keymat);
    pfreeany(st->st_esp.peer_keymat);
    freeanychunk(st->st_xauth_password);
#ifdef HAVE_LABELED_IPSEC
    pfreeany(st->sec_ctx);
#endif
    pfree(st);
}
Exemple #25
0
static int
SignFile(FILE *outFile, PRFileDesc *inFile, CERTCertificate *cert)
{
    SECItem data2sign;
    SECStatus rv;
    char *data;
    SECKEYPrivateKey *privKey;
    SECOidTag algID;
    PLArenaPool *arena;
    CERTSignedData sd;
    SECItem *result;

    if (outFile == NULL || inFile == NULL || cert == NULL)
        return -1;

    /* suck the file in */
    if (SECU_ReadDERFromFile(&data2sign, inFile, PR_FALSE,
                             PR_FALSE) != SECSuccess)
        return -1;

    privKey = NULL;    
    privKey = PK11_FindKeyByAnyCert(cert, NULL);

    algID = SEC_GetSignatureAlgorithmOidTag(privKey->keyType, SEC_OID_SHA1);
    if (algID == SEC_OID_UNKNOWN)
        return -1;
    
    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
    
    PORT_Memset(&sd, 0, sizeof(CERTSignedData));
    
    rv = SEC_SignData(&(sd.signature), data2sign.data, data2sign.len, privKey, algID);
    if (rv != SECSuccess) {
        fprintf (stderr, "Could not sign.\n");
        return -1;
    }
    sd.signature.len = sd.signature.len << 3;
    
    rv = SECOID_SetAlgorithmID(arena, &sd.signatureAlgorithm, algID, 0);
    if (rv != SECSuccess) {
        fprintf (stderr, "Could not set alg id.\n");
        return -1;
    }

    result = SEC_ASN1EncodeItem(arena, NULL, &sd, CERTSignatureDataTemplate);
    SECITEM_FreeItem(&(sd.signature), PR_FALSE);
    
    if (!result) {
        fprintf (stderr, "Could not encode.\n");
        return -1;
    }

    data = PL_Base64Encode((const char*)result->data, result->len, NULL);
    if (!data)
        return -1;
    
    fputs("signature:\n", outFile);
    fputs(data, outFile);
    fputs("\n", outFile);
    ExportPublicKey(outFile, cert);
    
    SECKEY_DestroyPrivateKey(privKey);
    PORT_FreeArena(arena, PR_FALSE);
    
    return 0;
}
Exemple #26
0
SECStatus NSS_CMSRecipientInfo_GetCertAndKey(NSSCMSRecipientInfo *ri,
                                             CERTCertificate** retcert,
                                             SECKEYPrivateKey** retkey)
{
    CERTCertificate* cert = NULL;
    NSSCMSRecipient** recipients = NULL;
    NSSCMSRecipientInfo* recipientInfos[2];
    SECStatus rv = SECSuccess;
    SECKEYPrivateKey* key = NULL;

    if (!ri)
        return SECFailure;
    
    if (!retcert && !retkey) {
        /* nothing requested, nothing found, success */
        return SECSuccess;
    }

    if (retcert) {
        *retcert = NULL;
    }
    if (retkey) {
        *retkey = NULL;
    }

    if (ri->cert) {
        cert = CERT_DupCertificate(ri->cert);
        if (!cert) {
            rv = SECFailure;
        }
    }
    if (SECSuccess == rv && !cert) {
        /* we don't have the cert, we have to look for it */
        /* first build an NSS_CMSRecipient */
        recipientInfos[0] = ri;
        recipientInfos[1] = NULL;

        recipients = nss_cms_recipient_list_create(recipientInfos);
        if (recipients) {
            /* now look for the cert and key */
            if (0 == PK11_FindCertAndKeyByRecipientListNew(recipients,
                ri->cmsg->pwfn_arg)) {
                cert = CERT_DupCertificate(recipients[0]->cert);
                key = SECKEY_CopyPrivateKey(recipients[0]->privkey);
            } else {
                rv = SECFailure;
            }

            nss_cms_recipient_list_destroy(recipients);
        }
        else {
            rv = SECFailure;
        }            
    } else if (SECSuccess == rv && cert && retkey) {
        /* we have the cert, we just need the key now */
        key = PK11_FindPrivateKeyFromCert(cert->slot, cert, ri->cmsg->pwfn_arg);
    }
    if (retcert) {
        *retcert = cert;
    } else {
        if (cert) {
            CERT_DestroyCertificate(cert);
        }
    }
    if (retkey) {
        *retkey = key;
    } else {
        if (key) {
            SECKEY_DestroyPrivateKey(key);
        }
    }

    return rv;
}
Exemple #27
0
// nsPKCS12Blob::ExportToFile
//
// Having already loaded the certs, form them into a blob (loading the keys
// also), encode the blob, and stuff it into the file.
//
// TODO: handle slots correctly
//       mirror "slotToUse" behavior from PSM 1.x
//       verify the cert array to start off with?
//       open output file as nsIFileStream object?
//       set appropriate error codes
nsresult
nsPKCS12Blob::ExportToFile(nsILocalFile *file, 
                           nsIX509Cert **certs, int numCerts)
{
  nsNSSShutDownPreventionLock locker;
  nsresult rv;
  SECStatus srv = SECSuccess;
  SEC_PKCS12ExportContext *ecx = NULL;
  SEC_PKCS12SafeInfo *certSafe = NULL, *keySafe = NULL;
  SECItem unicodePw;
  nsAutoString filePath;
  int i;
  nsCOMPtr<nsILocalFile> localFileRef;
  NS_ASSERTION(mToken, "Need to set the token before exporting");
  // init slot

  bool InformedUserNoSmartcardBackup = false;
  int numCertsExported = 0;

  rv = mToken->Login(true);
  if (NS_FAILED(rv)) goto finish;
  // get file password (unicode)
  unicodePw.data = NULL;
  rv = newPKCS12FilePassword(&unicodePw);
  if (NS_FAILED(rv)) goto finish;
  if (unicodePw.data == NULL) {
    handleError(PIP_PKCS12_USER_CANCELED);
    return NS_OK;
  }
  // what about slotToUse in psm 1.x ???
  // create export context
  ecx = SEC_PKCS12CreateExportContext(NULL, NULL, NULL /*slot*/, NULL);
  if (!ecx) {
    srv = SECFailure;
    goto finish;
  }
  // add password integrity
  srv = SEC_PKCS12AddPasswordIntegrity(ecx, &unicodePw, SEC_OID_SHA1);
  if (srv) goto finish;
#if 0
  // count the number of certs to export
  nrv = mCertArray->Count(&numCerts);
  if (NS_FAILED(nrv)) goto finish;
  // loop over the certs
  for (i=0; i<numCerts; i++) {
    nsCOMPtr<nsIX509Cert> cert;
    nrv = mCertArray->GetElementAt(i, getter_AddRefs(cert));
    if (NS_FAILED(nrv)) goto finish;
#endif
  for (i=0; i<numCerts; i++) {
//    nsNSSCertificate *cert = reinterpret_cast<nsNSSCertificate *>(certs[i]);
    nsNSSCertificate *cert = (nsNSSCertificate *)certs[i];
    // get it as a CERTCertificate XXX
    CERTCertificate *nssCert = NULL;
    CERTCertificateCleaner nssCertCleaner(nssCert);
    nssCert = cert->GetCert();
    if (!nssCert) {
      rv = NS_ERROR_FAILURE;
      goto finish;
    }
    // We can only successfully export certs that are on 
    // internal token.  Most, if not all, smart card vendors
    // won't let you extract the private key (in any way
    // shape or form) from the card.  So let's punt if 
    // the cert is not in the internal db.
    if (nssCert->slot && !PK11_IsInternal(nssCert->slot)) {
      // we aren't the internal token, see if the key is extractable.
      SECKEYPrivateKey *privKey=PK11_FindKeyByDERCert(nssCert->slot,
                                                      nssCert, this);

      if (privKey) {
        bool privKeyIsExtractable = isExtractable(privKey);

        SECKEY_DestroyPrivateKey(privKey);

        if (!privKeyIsExtractable) {
          if (!InformedUserNoSmartcardBackup) {
            InformedUserNoSmartcardBackup = true;
            handleError(PIP_PKCS12_NOSMARTCARD_EXPORT);
          }
          continue;
        }
      }
    }

    // XXX this is why, to verify the slot is the same
    // PK11_FindObjectForCert(nssCert, NULL, slot);
    // create the cert and key safes
    keySafe = SEC_PKCS12CreateUnencryptedSafe(ecx);
    if (!SEC_PKCS12IsEncryptionAllowed() || PK11_IsFIPS()) {
      certSafe = keySafe;
    } else {
      certSafe = SEC_PKCS12CreatePasswordPrivSafe(ecx, &unicodePw,
                           SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC);
    }
    if (!certSafe || !keySafe) {
      rv = NS_ERROR_FAILURE;
      goto finish;
    }
    // add the cert and key to the blob
    srv = SEC_PKCS12AddCertAndKey(ecx, certSafe, NULL, nssCert,
                                  CERT_GetDefaultCertDB(), // XXX
                                  keySafe, NULL, true, &unicodePw,
                      SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC);
    if (srv) goto finish;
    // cert was dup'ed, so release it
    ++numCertsExported;
  }
  
  if (!numCertsExported) goto finish;
  
  // prepare the instance to write to an export file
  this->mTmpFile = NULL;
  file->GetPath(filePath);
  // Use the nsCOMPtr var localFileRef so that
  // the reference to the nsILocalFile we create gets released as soon as
  // we're out of scope, ie when this function exits.
  if (filePath.RFind(".p12", true, -1, 4) < 0) {
    // We're going to add the .p12 extension to the file name just like
    // Communicator used to.  We create a new nsILocalFile and initialize
    // it with the new patch.
    filePath.AppendLiteral(".p12");
    localFileRef = do_CreateInstance(NS_LOCAL_FILE_CONTRACTID, &rv);
    if (NS_FAILED(rv)) goto finish;
    localFileRef->InitWithPath(filePath);
    file = localFileRef;
  }
  rv = file->OpenNSPRFileDesc(PR_RDWR|PR_CREATE_FILE|PR_TRUNCATE, 0664, 
                              &mTmpFile);
  if (NS_FAILED(rv) || !this->mTmpFile) goto finish;
  // encode and write
  srv = SEC_PKCS12Encode(ecx, write_export_file, this);
  if (srv) goto finish;
  handleError(PIP_PKCS12_BACKUP_OK);
finish:
  if (NS_FAILED(rv) || srv != SECSuccess) {
    handleError(PIP_PKCS12_BACKUP_FAILED);
  }
  if (ecx)
    SEC_PKCS12DestroyExportContext(ecx);
  if (this->mTmpFile) {
    PR_Close(this->mTmpFile);
    this->mTmpFile = NULL;
  }
  SECITEM_ZfreeItem(&unicodePw, false);
  return rv;
}

///////////////////////////////////////////////////////////////////////
//
//  private members
//
///////////////////////////////////////////////////////////////////////

// unicodeToItem
//
// For the NSS PKCS#12 library, must convert PRUnichars (shorts) to
// a buffer of octets.  Must handle byte order correctly.
// TODO: Is there a mozilla way to do this?  In the string lib?
void
nsPKCS12Blob::unicodeToItem(const PRUnichar *uni, SECItem *item)
{
  int len = 0;
  while (uni[len++] != 0);
  SECITEM_AllocItem(NULL, item, sizeof(PRUnichar) * len);
#ifdef IS_LITTLE_ENDIAN
  int i = 0;
  for (i=0; i<len; i++) {
    item->data[2*i  ] = (unsigned char )(uni[i] << 8);
    item->data[2*i+1] = (unsigned char )(uni[i]);
  }
#else
  memcpy(item->data, uni, item->len);
#endif
}
Exemple #28
0
/**
 * Writes out a copy of the MAR at src but with embedded signatures.
 * The passed in MAR file must not already be signed or an error will
 * be returned.
 *
 * @param  NSSConfigDir  The NSS directory containing the private key for signing
 * @param  certNames     The nicknames of the certificate to use for signing
 * @param  certCount     The number of certificate names contained in certNames.
 *                       One signature will be produced for each certificate.
 * @param  src           The path of the source MAR file to sign
 * @param  dest          The path of the MAR file to write out that is signed
 * @return 0 on success
 *         -1 on error
*/
int
mar_repackage_and_sign(const char *NSSConfigDir,
                       const char * const *certNames,
                       uint32_t certCount,
                       const char *src,
                       const char *dest)
{
  uint32_t offsetToIndex, dstOffsetToIndex, indexLength,
    numSignatures = 0, leftOver,
    signatureAlgorithmID, signatureSectionLength = 0;
  uint32_t signatureLengths[MAX_SIGNATURES];
  int64_t oldPos, sizeOfEntireMAR = 0, realSizeOfSrcMAR,
    signaturePlaceholderOffset, numBytesToCopy,
    numChunks, i;
  FILE *fpSrc = NULL, *fpDest = NULL;
  int rv = -1, hasSignatureBlock;
  SGNContext *ctxs[MAX_SIGNATURES];
  SECItem secItems[MAX_SIGNATURES];
  char buf[BLOCKSIZE];
  SECKEYPrivateKey *privKeys[MAX_SIGNATURES];
  CERTCertificate *certs[MAX_SIGNATURES];
  char *indexBuf = NULL;
  uint32_t k;

  memset(signatureLengths, 0, sizeof(signatureLengths));
  memset(ctxs, 0, sizeof(ctxs));
  memset(secItems, 0, sizeof(secItems));
  memset(privKeys, 0, sizeof(privKeys));
  memset(certs, 0, sizeof(certs));

  if (!NSSConfigDir || !certNames || certCount == 0 || !src || !dest) {
    fprintf(stderr, "ERROR: Invalid parameter passed in.\n");
    return -1;
  }

  if (NSSInitCryptoContext(NSSConfigDir)) {
    fprintf(stderr, "ERROR: Could not init config dir: %s\n", NSSConfigDir);
    goto failure;
  }

  PK11_SetPasswordFunc(SECU_GetModulePassword);

  fpSrc = fopen(src, "rb");
  if (!fpSrc) {
    fprintf(stderr, "ERROR: could not open source file: %s\n", src);
    goto failure;
  }

  fpDest = fopen(dest, "wb");
  if (!fpDest) {
    fprintf(stderr, "ERROR: could not create target file: %s\n", dest);
    goto failure;
  }

  /* Determine if the source MAR file has the new fields for signing or not */
  if (get_mar_file_info(src, &hasSignatureBlock, NULL, NULL, NULL, NULL)) {
    fprintf(stderr, "ERROR: could not determine if MAR is old or new.\n");
    goto failure;
  }

  for (k = 0; k < certCount; k++) {
    if (NSSSignBegin(certNames[k], &ctxs[k], &privKeys[k],
                     &certs[k], &signatureLengths[k])) {
      fprintf(stderr, "ERROR: NSSSignBegin failed\n");
      goto failure;
    }
  }

  /* MAR ID */
  if (ReadWriteAndUpdateSignatures(fpSrc, fpDest,
                                   buf, MAR_ID_SIZE,
                                   ctxs, certCount, "MAR ID")) {
    goto failure;
  }

  /* Offset to index */
  if (fread(&offsetToIndex, sizeof(offsetToIndex), 1, fpSrc) != 1) {
    fprintf(stderr, "ERROR: Could not read offset\n");
    goto failure;
  }
  offsetToIndex = ntohl(offsetToIndex);

  /* Get the real size of the MAR */
  oldPos = ftello(fpSrc);
  if (fseeko(fpSrc, 0, SEEK_END)) {
    fprintf(stderr, "ERROR: Could not seek to end of file.\n");
    goto failure;
  }
  realSizeOfSrcMAR = ftello(fpSrc);
  if (fseeko(fpSrc, oldPos, SEEK_SET)) {
    fprintf(stderr, "ERROR: Could not seek back to current location.\n");
    goto failure;
  }

  if (hasSignatureBlock) {
    /* Get the MAR length and adjust its size */
    if (fread(&sizeOfEntireMAR,
              sizeof(sizeOfEntireMAR), 1, fpSrc) != 1) {
      fprintf(stderr, "ERROR: Could read mar size\n");
      goto failure;
    }
    sizeOfEntireMAR = NETWORK_TO_HOST64(sizeOfEntireMAR);
    if (sizeOfEntireMAR != realSizeOfSrcMAR) {
      fprintf(stderr, "ERROR: Source MAR is not of the right size\n");
      goto failure;
    }

    /* Get the num signatures in the source file */
    if (fread(&numSignatures, sizeof(numSignatures), 1, fpSrc) != 1) {
      fprintf(stderr, "ERROR: Could read num signatures\n");
      goto failure;
    }
    numSignatures = ntohl(numSignatures);

    /* We do not support resigning, if you have multiple signatures,
       you must add them all at the same time. */
    if (numSignatures) {
      fprintf(stderr, "ERROR: MAR is already signed\n");
      goto failure;
    }
  } else {
    sizeOfEntireMAR = realSizeOfSrcMAR;
  }

  if (((int64_t)offsetToIndex) > sizeOfEntireMAR) {
    fprintf(stderr, "ERROR: Offset to index is larger than the file size.\n");
    goto failure;
  }

  /* Calculate the total signature block length */
  for (k = 0; k < certCount; k++) {
    signatureSectionLength += sizeof(signatureAlgorithmID) +
                              sizeof(signatureLengths[k]) +
                              signatureLengths[k];
  }
  dstOffsetToIndex = offsetToIndex;
  if (!hasSignatureBlock) {
    dstOffsetToIndex += sizeof(sizeOfEntireMAR) + sizeof(numSignatures);
  }
  dstOffsetToIndex += signatureSectionLength;

  /* Write out the index offset */
  dstOffsetToIndex = htonl(dstOffsetToIndex);
  if (WriteAndUpdateSignatures(fpDest, &dstOffsetToIndex,
                               sizeof(dstOffsetToIndex), ctxs, certCount,
                               "index offset")) {
    goto failure;
  }
  dstOffsetToIndex = ntohl(dstOffsetToIndex);

  /* Write out the new MAR file size */
  sizeOfEntireMAR += signatureSectionLength;
  if (!hasSignatureBlock) {
    sizeOfEntireMAR += sizeof(sizeOfEntireMAR) + sizeof(numSignatures);
  }

  /* Write out the MAR size */
  sizeOfEntireMAR = HOST_TO_NETWORK64(sizeOfEntireMAR);
  if (WriteAndUpdateSignatures(fpDest, &sizeOfEntireMAR,
                               sizeof(sizeOfEntireMAR), ctxs, certCount,
                               "size of MAR")) {
    goto failure;
  }
  sizeOfEntireMAR = NETWORK_TO_HOST64(sizeOfEntireMAR);

  /* Write out the number of signatures */
  numSignatures = certCount;
  numSignatures = htonl(numSignatures);
  if (WriteAndUpdateSignatures(fpDest, &numSignatures,
                               sizeof(numSignatures), ctxs, certCount,
                               "num signatures")) {
    goto failure;
  }
  numSignatures = ntohl(numSignatures);

  signaturePlaceholderOffset = ftello(fpDest);

  for (k = 0; k < certCount; k++) {
    /* Write out the signature algorithm ID, Only an ID of 1 is supported */
    signatureAlgorithmID = htonl(1);
    if (WriteAndUpdateSignatures(fpDest, &signatureAlgorithmID,
                                 sizeof(signatureAlgorithmID),
                                 ctxs, certCount, "num signatures")) {
      goto failure;
    }
    signatureAlgorithmID = ntohl(signatureAlgorithmID);

    /* Write out the signature length */
    signatureLengths[k] = htonl(signatureLengths[k]);
    if (WriteAndUpdateSignatures(fpDest, &signatureLengths[k],
                                 sizeof(signatureLengths[k]),
                                 ctxs, certCount, "signature length")) {
      goto failure;
    }
    signatureLengths[k] = ntohl(signatureLengths[k]);

    /* Write out a placeholder for the signature, we'll come back to this later
      *** THIS IS NOT SIGNED because it is a placeholder that will be replaced
          below, plus it is going to be the signature itself. *** */
    memset(buf, 0, sizeof(buf));
    if (fwrite(buf, signatureLengths[k], 1, fpDest) != 1) {
      fprintf(stderr, "ERROR: Could not write signature length\n");
      goto failure;
    }
  }

  /* Write out the rest of the MAR excluding the index header and index
     offsetToIndex unfortunately has to remain 32-bit because for backwards
     compatibility with the old MAR file format. */
  if (ftello(fpSrc) > ((int64_t)offsetToIndex)) {
    fprintf(stderr, "ERROR: Index offset is too small.\n");
    goto failure;
  }
  numBytesToCopy = ((int64_t)offsetToIndex) - ftello(fpSrc);
  numChunks = numBytesToCopy / BLOCKSIZE;
  leftOver = numBytesToCopy % BLOCKSIZE;

  /* Read each file and write it to the MAR file */
  for (i = 0; i < numChunks; ++i) {
    if (ReadWriteAndUpdateSignatures(fpSrc, fpDest, buf,
                                     BLOCKSIZE, ctxs, certCount,
                                     "content block")) {
      goto failure;
    }
  }

  /* Write out the left over */
  if (ReadWriteAndUpdateSignatures(fpSrc, fpDest, buf,
                                   leftOver, ctxs, certCount,
                                   "left over content block")) {
    goto failure;
  }

  /* Length of the index */
  if (ReadWriteAndUpdateSignatures(fpSrc, fpDest, &indexLength,
                                   sizeof(indexLength), ctxs, certCount,
                                   "index length")) {
    goto failure;
  }
  indexLength = ntohl(indexLength);

  /* Consume the index and adjust each index by signatureSectionLength */
  indexBuf = malloc(indexLength);
  if (fread(indexBuf, indexLength, 1, fpSrc) != 1) {
    fprintf(stderr, "ERROR: Could not read index\n");
    goto failure;
  }

  /* Adjust each entry in the index */
  if (hasSignatureBlock) {
    AdjustIndexContentOffsets(indexBuf, indexLength, signatureSectionLength);
  } else {
    AdjustIndexContentOffsets(indexBuf, indexLength,
                              sizeof(sizeOfEntireMAR) +
                              sizeof(numSignatures) +
                              signatureSectionLength);
  }

  if (WriteAndUpdateSignatures(fpDest, indexBuf,
                               indexLength, ctxs, certCount, "index")) {
    goto failure;
  }

  /* Ensure that we don't sign a file that is too large to be accepted by
     the verification function. */
  if (ftello(fpDest) > MAX_SIZE_OF_MAR_FILE) {
    goto failure;
  }

  for (k = 0; k < certCount; k++) {
    /* Get the signature */
    if (SGN_End(ctxs[k], &secItems[k]) != SECSuccess) {
      fprintf(stderr, "ERROR: Could not end signature context\n");
      goto failure;
    }
    if (signatureLengths[k] != secItems[k].len) {
      fprintf(stderr, "ERROR: Signature is not the expected length\n");
      goto failure;
    }
  }

  /* Get back to the location of the signature placeholder */
  if (fseeko(fpDest, signaturePlaceholderOffset, SEEK_SET)) {
    fprintf(stderr, "ERROR: Could not seek to signature offset\n");
    goto failure;
  }

  for (k = 0; k < certCount; k++) {
    /* Skip to the position of the next signature */
    if (fseeko(fpDest, sizeof(signatureAlgorithmID) +
               sizeof(signatureLengths[k]), SEEK_CUR)) {
      fprintf(stderr, "ERROR: Could not seek to signature offset\n");
      goto failure;
    }

    /* Write out the calculated signature.
      *** THIS IS NOT SIGNED because it is the signature itself. *** */
    if (fwrite(secItems[k].data, secItems[k].len, 1, fpDest) != 1) {
      fprintf(stderr, "ERROR: Could not write signature\n");
      goto failure;
    }
  }

  rv = 0;
failure:
  if (fpSrc) {
    fclose(fpSrc);
  }

  if (fpDest) {
    fclose(fpDest);
  }

  if (rv) {
    remove(dest);
  }

  if (indexBuf) {
    free(indexBuf);
  }

  /* Cleanup */
  for (k = 0; k < certCount; k++) {
    if (ctxs[k]) {
      SGN_DestroyContext(ctxs[k], PR_TRUE);
    }

    if (certs[k]) {
      CERT_DestroyCertificate(certs[k]);
    }

    if (privKeys[k]) {
      SECKEY_DestroyPrivateKey(privKeys[k]);
    }

    SECITEM_FreeItem(&secItems[k], PR_FALSE);
  }

  if (rv) {
    remove(dest);
  }

  return rv;
}
Exemple #29
0
/*
 * generate an RSA signature key
 *
 * e is fixed at 3, without discussion.  That would not be wise if these
 * keys were to be used for encryption, but for signatures there are some
 * real speed advantages.
 * See also: https://www.imperialviolet.org/2012/03/16/rsae.html
 */
void rsasigkey(int nbits, int seedbits, char *configdir, char *password)
{
	SECStatus rv;
	PK11RSAGenParams rsaparams = { nbits, (long) E };
	secuPWData pwdata = { PW_NONE, NULL };
	PK11SlotInfo *slot = NULL;
	SECKEYPrivateKey *privkey = NULL;
	SECKEYPublicKey *pubkey = NULL;
	realtime_t now = realnow();

	if (password == NULL) {
		pwdata.source = PW_NONE;
	} else {
		/* check if passwd == configdir/nsspassword */
		size_t cdl = strlen(configdir);
		size_t pwl = strlen(password);
		static const char suf[] = "/nsspassword";

		if (pwl == cdl + sizeof(suf) - 1 &&
			memeq(password, configdir, cdl) &&
			memeq(password + cdl, suf, sizeof(suf)))
			pwdata.source = PW_FROMFILE;
		else
			pwdata.source = PW_PLAINTEXT;
	}
	pwdata.data = password;

	lsw_nss_buf_t err;
	if (!lsw_nss_setup(configdir, FALSE/*rw*/, GetModulePassword, err)) {
		fprintf(stderr, "%s: %s\n", me, err);
		exit(1);
	}

#ifdef FIPS_CHECK
	if (PK11_IsFIPS() && !FIPSCHECK_verify(NULL, NULL)) {
		fprintf(stderr,
			"FIPS HMAC integrity verification test failed.\n");
		exit(1);
	}
#endif

	if (PK11_IsFIPS() && password == NULL) {
		fprintf(stderr,
			"%s: On FIPS mode a password is required\n",
			me);
		exit(1);
	}

	/* Good for now but someone may want to use a hardware token */
	slot = PK11_GetInternalKeySlot();
	/* In which case this may be better */
	/* slot = PK11_GetBestSlot(CKM_RSA_PKCS_KEY_PAIR_GEN, password ? &pwdata : NULL); */
	/* or the user may specify the name of a token. */

#if 0
	if (PK11_IsFIPS() || !PK11_IsInternal(slot)) {
		rv = PK11_Authenticate(slot, PR_FALSE, &pwdata);
		if (rv != SECSuccess) {
			fprintf(stderr, "%s: could not authenticate to token '%s'\n",
				me, PK11_GetTokenName(slot));
			return;
		}
	}
#endif /* 0 */

	/* Do some random-number initialization. */
	UpdateNSS_RNG(seedbits);
	/* Log in to the token */
	if (password != NULL) {
		rv = PK11_Authenticate(slot, PR_FALSE, &pwdata);
		if (rv != SECSuccess) {
			fprintf(stderr,
				"%s: could not authenticate to token '%s'\n",
				me, PK11_GetTokenName(slot));
			return;
		}
	}
	privkey = PK11_GenerateKeyPair(slot,
				       CKM_RSA_PKCS_KEY_PAIR_GEN,
				       &rsaparams, &pubkey,
				       PR_TRUE,
				       password != NULL? PR_TRUE : PR_FALSE,
				       &pwdata);
	/* inTheToken, isSensitive, passwordCallbackFunction */
	if (privkey == NULL) {
		fprintf(stderr,
			"%s: key pair generation failed: \"%d\"\n", me,
			PORT_GetError());
		return;
	}

	chunk_t public_modulus = {
		.ptr = pubkey->u.rsa.modulus.data,
		.len = pubkey->u.rsa.modulus.len,
	};
	chunk_t public_exponent = {
		.ptr = pubkey->u.rsa.publicExponent.data,
		.len = pubkey->u.rsa.publicExponent.len,
	};

	char *hex_ckaid;
	{
		SECItem *ckaid = PK11_GetLowLevelKeyIDForPrivateKey(privkey);
		if (ckaid == NULL) {
			fprintf(stderr, "%s: 'CKAID' calculation failed\n", me);
			exit(1);
		}
		hex_ckaid = strdup(conv(ckaid->data, ckaid->len, 16));
		SECITEM_FreeItem(ckaid, PR_TRUE);
	}

	/*privkey->wincx = &pwdata;*/
	PORT_Assert(pubkey != NULL);
	fprintf(stderr, "Generated RSA key pair with CKAID %s was stored in the NSS database\n",
		hex_ckaid);

	/* and the output */
	report("output...\n");  /* deliberate extra newline */
	printf("\t# RSA %d bits   %s   %s", nbits, outputhostname,
		ctime(&now.real_secs));
	/* ctime provides \n */
	printf("\t# for signatures only, UNSAFE FOR ENCRYPTION\n");

	printf("\t#ckaid=%s\n", hex_ckaid);

	/* RFC2537/RFC3110-ish format */
	{
		char *bundle = base64_bundle(E, public_modulus);
		printf("\t#pubkey=%s\n", bundle);
		pfree(bundle);
	}

	printf("\tModulus: 0x%s\n", conv(public_modulus.ptr, public_modulus.len, 16));
	printf("\tPublicExponent: 0x%s\n", conv(public_exponent.ptr, public_exponent.len, 16));

	if (hex_ckaid != NULL)
		free(hex_ckaid);
	if (privkey != NULL)
		SECKEY_DestroyPrivateKey(privkey);
	if (pubkey != NULL)
		SECKEY_DestroyPublicKey(pubkey);

	lsw_nss_shutdown(LSW_NSS_CLEANUP);
}

/*
 * getrandom - get some random bytes from /dev/random (or wherever)
 * NOTE: This is only used for additional seeding of the NSS RNG
 */
void getrandom(size_t nbytes, unsigned char *buf)
{
	size_t ndone;
	int dev;
	ssize_t got;

	dev = open(device, 0);
	if (dev < 0) {
		fprintf(stderr, "%s: could not open %s (%s)\n", me,
			device, strerror(errno));
		exit(1);
	}

	ndone = 0;
	if (verbose) {
		fprintf(stderr, "getting %d random seed bytes for NSS from %s...\n",
			(int) nbytes * BITS_PER_BYTE,
			device);
	}
	while (ndone < nbytes) {
		got = read(dev, buf + ndone, nbytes - ndone);
		if (got < 0) {
			fprintf(stderr, "%s: read error on %s (%s)\n", me,
				device, strerror(errno));
			exit(1);
		}
		if (got == 0) {
			fprintf(stderr, "%s: eof on %s!?!\n", me, device);
			exit(1);
		}
		ndone += got;
	}

	close(dev);
}

/*
   - conv - convert bits to output in specified datatot format
 * NOTE: result points into a STATIC buffer
 */
static const char *conv(const unsigned char *bits, size_t nbytes, int format)
{
	static char convbuf[MAXBITS / 4 + 50];  /* enough for hex */
	size_t n;

	n = datatot(bits, nbytes, format, convbuf, sizeof(convbuf));
	if (n == 0) {
		fprintf(stderr, "%s: can't-happen convert error\n", me);
		exit(1);
	}
	if (n > sizeof(convbuf)) {
		fprintf(stderr,
			"%s: can't-happen convert overflow (need %d)\n",
			me, (int) n);
		exit(1);
	}
	return convbuf;
}

/*
   - report - report progress, if indicated
 */
void report(msg)
char *msg;
{
	if (!verbose)
		return;

	fprintf(stderr, "%s\n", msg);
}
Exemple #30
0
SECStatus 
SSL_CanBypass(CERTCertificate *cert, SECKEYPrivateKey *srvPrivkey,
	      PRUint32 protocolmask, PRUint16 *ciphersuites, int nsuites,
              PRBool *pcanbypass, void *pwArg)
{   SECStatus	      rv;
    int		      i;
    PRUint16	      suite;
    PK11SymKey *      pms = NULL;
    SECKEYPublicKey * srvPubkey = NULL;
    KeyType	      privKeytype;
    PK11SlotInfo *    slot = NULL;
    SECItem           param;
    CK_VERSION 	      version;
    CK_MECHANISM_TYPE mechanism_array[2];
    SECItem           enc_pms = {siBuffer, NULL, 0};
    PRBool	      isTLS = PR_FALSE;
    SSLCipherSuiteInfo csdef;
    PRBool	      testrsa = PR_FALSE;
    PRBool	      testrsa_export = PR_FALSE;
    PRBool	      testecdh = PR_FALSE;
    PRBool	      testecdhe = PR_FALSE;
#ifdef NSS_ENABLE_ECC
    SECKEYECParams ecParams = { siBuffer, NULL, 0 };
#endif

    if (!cert || !srvPrivkey || !ciphersuites || !pcanbypass) {
	PORT_SetError(SEC_ERROR_INVALID_ARGS);
        return SECFailure;
    }
    
    srvPubkey = CERT_ExtractPublicKey(cert);
    if (!srvPubkey)
        return SECFailure;
	
    *pcanbypass = PR_TRUE;
    rv = SECFailure;
    
    /* determine which KEAs to test */
    /* 0 (SSL_NULL_WITH_NULL_NULL) is used as a list terminator because
     * SSL3 and TLS specs forbid negotiating that cipher suite number.
     */
    for (i=0; i < nsuites && (suite = *ciphersuites++) != 0; i++) {
	/* skip SSL2 cipher suites and ones NSS doesn't support */
	if (SSL_GetCipherSuiteInfo(suite, &csdef, sizeof(csdef)) != SECSuccess
	    || SSL_IS_SSL2_CIPHER(suite) )
	    continue;
	switch (csdef.keaType) {
	case ssl_kea_rsa:
	    switch (csdef.cipherSuite) {
	    case TLS_RSA_EXPORT1024_WITH_RC4_56_SHA:
	    case TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA:
	    case SSL_RSA_EXPORT_WITH_RC4_40_MD5:
	    case SSL_RSA_EXPORT_WITH_RC2_CBC_40_MD5:
		testrsa_export = PR_TRUE;
	    }
	    if (!testrsa_export)
		testrsa = PR_TRUE;
	    break;
	case ssl_kea_ecdh:
	    if (strcmp(csdef.keaTypeName, "ECDHE") == 0) /* ephemeral? */
		testecdhe = PR_TRUE;
	    else
		testecdh = PR_TRUE;
	    break;
	case ssl_kea_dh:
	    /* this is actually DHE */
	default:
	    continue;
	}
    }
    
    /* For each protocol try to derive and extract an MS.
     * Failure of function any function except MS extract means
     * continue with the next cipher test. Stop testing when the list is
     * exhausted or when the first MS extract--not derive--fails.
     */
    privKeytype = SECKEY_GetPrivateKeyType(srvPrivkey);
    protocolmask &= SSL_CBP_SSL3|SSL_CBP_TLS1_0;
    while (protocolmask) {
	if (protocolmask & SSL_CBP_SSL3) {
	    isTLS = PR_FALSE;
	    protocolmask ^= SSL_CBP_SSL3;
	} else {
	    isTLS = PR_TRUE;
	    protocolmask ^= SSL_CBP_TLS1_0;
	}

	if (privKeytype == rsaKey && testrsa_export) {
	    if (PK11_GetPrivateModulusLen(srvPrivkey) > EXPORT_RSA_KEY_LENGTH) {
		*pcanbypass = PR_FALSE;
		rv = SECSuccess;
		break;
	    } else
		testrsa = PR_TRUE;
	}
	for (; privKeytype == rsaKey && testrsa; ) {
	    /* TLS_RSA */
	    unsigned char     rsaPmsBuf[SSL3_RSA_PMS_LENGTH];
	    unsigned int      outLen = 0;
	    CK_MECHANISM_TYPE target;
	    SECStatus	      irv;
	    
	    mechanism_array[0] = CKM_SSL3_PRE_MASTER_KEY_GEN;
	    mechanism_array[1] = CKM_RSA_PKCS;

	    slot = PK11_GetBestSlotMultiple(mechanism_array, 2, pwArg);
	    if (slot == NULL) {
		PORT_SetError(SSL_ERROR_TOKEN_SLOT_NOT_FOUND);
		break;
	    }

	    /* Generate the pre-master secret ...  (client side) */
	    version.major = 3 /*MSB(clientHelloVersion)*/;
	    version.minor = 0 /*LSB(clientHelloVersion)*/;
	    param.data = (unsigned char *)&version;
	    param.len  = sizeof version;
	    pms = PK11_KeyGen(slot, CKM_SSL3_PRE_MASTER_KEY_GEN, &param, 0, pwArg);
	    PK11_FreeSlot(slot);
	    if (!pms)
		break;
	    /* now wrap it */
	    enc_pms.len  = SECKEY_PublicKeyStrength(srvPubkey);
	    enc_pms.data = (unsigned char*)PORT_Alloc(enc_pms.len);
	    if (enc_pms.data == NULL) {
	        PORT_SetError(PR_OUT_OF_MEMORY_ERROR);
	        break;
	    }
	    irv = PK11_PubWrapSymKey(CKM_RSA_PKCS, srvPubkey, pms, &enc_pms);
	    if (irv != SECSuccess) 
		break;
	    PK11_FreeSymKey(pms);
	    pms = NULL;
	    /* now do the server side--check the triple bypass first */
	    rv = PK11_PrivDecryptPKCS1(srvPrivkey, rsaPmsBuf, &outLen,
				       sizeof rsaPmsBuf,
				       (unsigned char *)enc_pms.data,
				       enc_pms.len);
	    /* if decrypt worked we're done with the RSA test */
	    if (rv == SECSuccess) {
		*pcanbypass = PR_TRUE;
		break;
	    }
	    /* check for fallback to double bypass */
	    target = isTLS ? CKM_TLS_MASTER_KEY_DERIVE
			: CKM_SSL3_MASTER_KEY_DERIVE;
	    pms = PK11_PubUnwrapSymKey(srvPrivkey, &enc_pms,
				       target, CKA_DERIVE, 0);
	    rv = ssl_canExtractMS(pms, isTLS, PR_FALSE, pcanbypass);
	    if (rv == SECSuccess && *pcanbypass == PR_FALSE)
		goto done;
	    break;
	}

	/* Check for NULL to avoid double free. 
	 * SECItem_FreeItem sets data NULL in secitem.c#265 
	 */
	if (enc_pms.data != NULL) {
	    SECITEM_FreeItem(&enc_pms, PR_FALSE);
        }
#ifdef NSS_ENABLE_ECC
	for (; (privKeytype == ecKey && ( testecdh || testecdhe)) ||
	       (privKeytype == rsaKey && testecdhe); ) {
	    CK_MECHANISM_TYPE target;
	    SECKEYPublicKey  *keapub = NULL;
	    SECKEYPrivateKey *keapriv;
	    SECKEYPublicKey  *cpub = NULL; /* client's ephemeral ECDH keys */
	    SECKEYPrivateKey *cpriv = NULL;
	    SECKEYECParams   *pecParams = NULL;

	    if (privKeytype == ecKey && testecdhe) {
		/* TLS_ECDHE_ECDSA */
		pecParams = &srvPubkey->u.ec.DEREncodedParams;
	    } else if (privKeytype == rsaKey && testecdhe) {
		/* TLS_ECDHE_RSA */
		ECName       ec_curve;
		int		 serverKeyStrengthInBits;
		int		 signatureKeyStrength;
		int		 requiredECCbits;

		/* find a curve of equivalent strength to the RSA key's */
		requiredECCbits = PK11_GetPrivateModulusLen(srvPrivkey);
		if (requiredECCbits < 0)
		    break;
		requiredECCbits *= BPB;
		serverKeyStrengthInBits = srvPubkey->u.rsa.modulus.len;
		if (srvPubkey->u.rsa.modulus.data[0] == 0) {
		    serverKeyStrengthInBits--;
		}
		/* convert to strength in bits */
		serverKeyStrengthInBits *= BPB;

		signatureKeyStrength =
		    SSL_RSASTRENGTH_TO_ECSTRENGTH(serverKeyStrengthInBits);

		if ( requiredECCbits > signatureKeyStrength ) 
		     requiredECCbits = signatureKeyStrength;

		ec_curve =
		    ssl3_GetCurveWithECKeyStrength(SSL3_SUPPORTED_CURVES_MASK,
						   requiredECCbits);
		rv = ssl3_ECName2Params(NULL, ec_curve, &ecParams);
		if (rv == SECFailure) {
		    break;
		}
		pecParams = &ecParams;
	    }

	    if (testecdhe) {
		/* generate server's ephemeral keys */
		keapriv = SECKEY_CreateECPrivateKey(pecParams, &keapub, NULL); 
		if (!keapriv || !keapub) {
		    if (keapriv)
			SECKEY_DestroyPrivateKey(keapriv);
		    if (keapub)
			SECKEY_DestroyPublicKey(keapub);
		    PORT_SetError(SEC_ERROR_KEYGEN_FAIL);
		    rv = SECFailure;
		    break;
		}
	    } else {
		/* TLS_ECDH_ECDSA */
		keapub = srvPubkey;
		keapriv = srvPrivkey;
		pecParams = &srvPubkey->u.ec.DEREncodedParams;
	    }

	    /* perform client side ops */
	    /* generate a pair of ephemeral keys using server's parms */
	    cpriv = SECKEY_CreateECPrivateKey(pecParams, &cpub, NULL);
	    if (!cpriv || !cpub) {
		if (testecdhe) {
		    SECKEY_DestroyPrivateKey(keapriv);
		    SECKEY_DestroyPublicKey(keapub);
		}
		PORT_SetError(SEC_ERROR_KEYGEN_FAIL);
		rv = SECFailure;
		break;
	    }
	    /* now do the server side */
	    /* determine the PMS using client's public value */
	    target = isTLS ? CKM_TLS_MASTER_KEY_DERIVE_DH
			   : CKM_SSL3_MASTER_KEY_DERIVE_DH;
	    pms = PK11_PubDeriveWithKDF(keapriv, cpub, PR_FALSE, NULL, NULL,
				    CKM_ECDH1_DERIVE,
				    target,
				    CKA_DERIVE, 0, CKD_NULL, NULL, NULL);
	    rv = ssl_canExtractMS(pms, isTLS, PR_TRUE, pcanbypass);
	    SECKEY_DestroyPrivateKey(cpriv);
	    SECKEY_DestroyPublicKey(cpub);
	    if (testecdhe) {
		SECKEY_DestroyPrivateKey(keapriv);
		SECKEY_DestroyPublicKey(keapub);
	    }
	    if (rv == SECSuccess && *pcanbypass == PR_FALSE)
		goto done;
	    break;
	}
	/* Check for NULL to avoid double free. */
	if (ecParams.data != NULL) {
	    PORT_Free(ecParams.data);
	    ecParams.data = NULL;
	}
#endif /* NSS_ENABLE_ECC */
	if (pms)
	    PK11_FreeSymKey(pms);
    }

    /* *pcanbypass has been set */
    rv = SECSuccess;
    
  done:
    if (pms)
	PK11_FreeSymKey(pms);

    /* Check for NULL to avoid double free. 
     * SECItem_FreeItem sets data NULL in secitem.c#265 
     */
    if (enc_pms.data != NULL) {
    	SECITEM_FreeItem(&enc_pms, PR_FALSE);
    }
#ifdef NSS_ENABLE_ECC
    if (ecParams.data != NULL) {
        PORT_Free(ecParams.data);
        ecParams.data = NULL;
    }
#endif /* NSS_ENABLE_ECC */

    if (srvPubkey) {
    	SECKEY_DestroyPublicKey(srvPubkey);
	srvPubkey = NULL;
    }


    return rv;
}