Example #1
0
static void
purple_aes_cipher_nss_cleanup(PurpleAESCipherNSSContext *context)
{
	g_return_if_fail(context != NULL);

	if (context->enc_context != NULL)
		PK11_DestroyContext(context->enc_context, TRUE);
	if (context->sec_param != NULL)
		SECITEM_FreeItem(context->sec_param, TRUE);
	if (context->sym_key != NULL)
		PK11_FreeSymKey(context->sym_key);
	if (context->slot != NULL)
		PK11_FreeSlot(context->slot);

	memset(context, 0, sizeof(PurpleAESCipherNSSContext));
}
Example #2
0
static void
ssl_FreeCipherSpec(ssl3CipherSpec *spec)
{
    SSL_TRC(10, ("%d: SSL[-]: Freeing %s spec %d. epoch=%d",
                 SSL_GETPID(), SPEC_DIR(spec), spec, spec->epoch));

    PR_REMOVE_LINK(&spec->link);

    /*  PORT_Assert( ss->opt.noLocks || ssl_HaveSpecWriteLock(ss)); Don't have ss! */
    if (spec->cipherContext) {
        PK11_DestroyContext(spec->cipherContext, PR_TRUE);
    }
    PK11_FreeSymKey(spec->masterSecret);
    ssl_DestroyKeyMaterial(&spec->keyMaterial);

    PORT_ZFree(spec, sizeof(*spec));
}
Example #3
0
/*
 * Free up a Cipher Context
 */
void
PK11_DestroyContext(PK11Context *context, PRBool freeit)
{
    pk11_CloseSession(context->slot, context->session, context->ownSession);
    /* initialize the critical fields of the context */
    if (context->savedData != NULL)
        PORT_Free(context->savedData);
    if (context->key)
        PK11_FreeSymKey(context->key);
    if (context->param && context->param != &pk11_null_params)
        SECITEM_FreeItem(context->param, PR_TRUE);
    if (context->sessionLock)
        PZ_DestroyLock(context->sessionLock);
    PK11_FreeSlot(context->slot);
    if (freeit)
        PORT_Free(context);
}
Example #4
0
/*
 * DestroyPk11PinStore
 */
void DestroyPk11PinStore(Pk11PinStore *store)
{
    if (store == 0) return;

    if (store->params) {
        SECITEM_ZfreeItem(store->params, PR_TRUE);
    }

    if (store->key) {
        PK11_FreeSymKey(store->key);
    }

    if (store->crypt) {
        memset(store->crypt, 0, store->length);
        free(store->crypt);
    }

    free(store);
}
Example #5
0
char *oauth_sign_hmac_sha1_raw (const char *m, const size_t ml, const char *k, const size_t kl) {
  PK11SlotInfo  *slot = NULL;
  PK11SymKey    *pkey = NULL;
  PK11Context   *context = NULL;
  unsigned char  digest[20]; // Is there a way to tell how large the output is?
  unsigned int   len;
  SECStatus      s;
  SECItem        keyItem, noParams;
  char          *rv=NULL;

  keyItem.type = siBuffer;
  keyItem.data = (unsigned char*) k;
  keyItem.len = kl;

  noParams.type = siBuffer;
  noParams.data = NULL;
  noParams.len = 0;

  oauth_init_nss();

  slot = PK11_GetInternalKeySlot();
  if (!slot) goto looser;
  pkey = PK11_ImportSymKey(slot, CKM_SHA_1_HMAC, PK11_OriginUnwrap, CKA_SIGN, &keyItem, NULL);
  if (!pkey)  goto looser;
  context = PK11_CreateContextBySymKey(CKM_SHA_1_HMAC, CKA_SIGN, pkey, &noParams);
  if (!context) goto looser;

  s = PK11_DigestBegin(context);
  if (s != SECSuccess) goto looser;
  s = PK11_DigestOp(context, (unsigned char*) m, ml);
  if (s != SECSuccess) goto looser;
  s = PK11_DigestFinal(context, digest, &len, sizeof digest);
  if (s != SECSuccess) goto looser;

  rv=oauth_encode_base64(len, digest);

looser:
  if (context) PK11_DestroyContext(context, PR_TRUE);
  if (pkey) PK11_FreeSymKey(pkey);
  if (slot) PK11_FreeSlot(slot);
  return rv;
}
Example #6
0
/*
 * NSS_CMSEncryptedData_Decode_BeforeData - find bulk key & set up decryption
 */
SECStatus
NSS_CMSEncryptedData_Decode_BeforeData(NSSCMSEncryptedData *encd)
{
    PK11SymKey *bulkkey = NULL;
    NSSCMSContentInfo *cinfo;
    SECAlgorithmID *bulkalg;
    SECStatus rv = SECFailure;

    cinfo = &(encd->contentInfo);

    bulkalg = NSS_CMSContentInfo_GetContentEncAlg(cinfo);

    if (encd->cmsg->decrypt_key_cb == NULL)	/* no callback? no key../ */
	goto loser;

    bulkkey = (*encd->cmsg->decrypt_key_cb)(encd->cmsg->decrypt_key_cb_arg, bulkalg);
    if (bulkkey == NULL)
	/* no success finding a bulk key */
	goto loser;

    NSS_CMSContentInfo_SetBulkKey(cinfo, bulkkey);

    rv = NSS_CMSContentInfo_Private_Init(cinfo);
    if (rv != SECSuccess) {
	goto loser;
    }
    rv = SECFailure;

    cinfo->privateInfo->ciphcx = NSS_CMSCipherContext_StartDecrypt(bulkkey, bulkalg);
    if (cinfo->privateInfo->ciphcx == NULL)
	goto loser;		/* error has been set by NSS_CMSCipherContext_StartDecrypt */


    /* we are done with (this) bulkkey now. */
    PK11_FreeSymKey(bulkkey);

    rv = SECSuccess;

loser:
    return rv;
}
Example #7
0
/***********************************************************************
 *
 * J S S _ P K 1 1 _ w r a p S y m K e y

 * Puts a Symmetric Key into a Java object.
 * (Does NOT perform a cryptographic "wrap" operation.)
 * symKey: will be stored in a Java wrapper.
 * Returns: a new PK11SymKey, or NULL if an exception occurred.
 */
jobject
JSS_PK11_wrapSymKey(JNIEnv *env, PK11SymKey **symKey)
{
    jclass keyClass;
    jmethodID constructor;
    jbyteArray ptrArray;
    jobject Key=NULL;

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

    /* find the class */
    keyClass = (*env)->FindClass(env, PK11SYMKEY_CLASS_NAME);
    if( keyClass == NULL ) {
        ASSERT_OUTOFMEM(env);
        goto finish;
    }

    /* find the constructor */
    constructor = (*env)->GetMethodID(env, keyClass,
                                      PLAIN_CONSTRUCTOR,
                                      PK11SYMKEY_CONSTRUCTOR_SIG);
    if(constructor == NULL) {
        ASSERT_OUTOFMEM(env);
        goto finish;
    }

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

finish:
    if(Key == NULL) {
        PK11_FreeSymKey(*symKey);
    }
    *symKey = NULL;
    return Key;
}
Example #8
0
/*
 * Create a context from a key. We really should make sure we aren't using
 * the same key in multiple session!
 */
PK11Context *
PK11_CreateContextBySymKey(CK_MECHANISM_TYPE type, CK_ATTRIBUTE_TYPE operation,
                           PK11SymKey *symKey, SECItem *param)
{
    PK11SymKey *newKey;
    PK11Context *context;

    /* if this slot doesn't support the mechanism, go to a slot that does */
    newKey = pk11_ForceSlot(symKey, type, operation);
    if (newKey == NULL) {
        PK11_ReferenceSymKey(symKey);
    } else {
        symKey = newKey;
    }

    /* Context Adopts the symKey.... */
    context = pk11_CreateNewContextInSlot(type, symKey->slot, operation, symKey,
                                          param);
    PK11_FreeSymKey(symKey);
    return context;
}
Example #9
0
void
nsKeyObject::CleanUp()
{
  switch (mKeyType) {
    case nsIKeyObject::SYM_KEY:
      PK11_FreeSymKey(mSymKey);
      break;
    
    case nsIKeyObject::PRIVATE_KEY:
      PK11_DeleteTokenPrivateKey(mPrivateKey, PR_TRUE /* force */);
      break;

    case nsIKeyObject::PUBLIC_KEY:
      PK11_DeleteTokenPublicKey(mPublicKey);
      break;
    
    default:
      // probably not initialized, do nothing
      break;
  }
  mKeyType = 0;
}
Example #10
0
/*
 * create a symetric key:
 *      Slot is the slot to create the key in.
 *      type is the mechanism type 
 *      owner is does this symKey structure own it's object handle (rare
 *        that this is false).
 *      needSession means the returned symKey will return with a valid session
 *        allocated already.
 */
static PK11SymKey *
pk11_CreateSymKey(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, 
		  PRBool owner, PRBool needSession, void *wincx)
{

    PK11SymKey *symKey = pk11_getKeyFromList(slot, needSession);

    if (symKey == NULL) {
	return NULL;
    }
    /* if needSession was specified, make sure we have a valid session.
     * callers which specify needSession as false should do their own
     * check of the session before returning the symKey */
    if (needSession && symKey->session == CK_INVALID_SESSION) {
    	PK11_FreeSymKey(symKey);
	PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
	return NULL;
    }

    symKey->type = type;
    symKey->data.type = siBuffer;
    symKey->data.data = NULL;
    symKey->data.len = 0;
    symKey->owner = owner;
    symKey->objectID = CK_INVALID_HANDLE;
    symKey->slot = slot;
    symKey->series = slot->series;
    symKey->cx = wincx;
    symKey->size = 0;
    symKey->refCount = 1;
    symKey->origin = PK11_OriginNULL;
    symKey->parent = NULL;
    symKey->freeFunc = NULL;
    symKey->userData = NULL;
    PK11_ReferenceSlot(slot);
    return symKey;
}
Example #11
0
SECStatus
ListKeys(PK11SlotInfo *slot, int *printLabel, void *pwd) {
    PK11SymKey *keyList;
    SECStatus rv = PK11_Authenticate(slot, PR_FALSE, pwd);
    if (rv != SECSuccess) {
        return rv;;
    }

    keyList = PK11_ListFixedKeysInSlot(slot, NULL, pwd);
    if (keyList) {
	if (*printLabel) {
            printf("     Name            Len Strength     Type    Data\n");
	    *printLabel = 0;
	}
	printf("%s:\n",PK11_GetTokenName(slot));
    }
    while (keyList) {
        PK11SymKey *freeKey = keyList;
        PrintKey(keyList);
        keyList = PK11_GetNextSymKey(keyList);
        PK11_FreeSymKey(freeKey);
    }
    return SECSuccess;
}
Example #12
0
/*
 * put together the various PK11_Create_Context calls used by different
 * parts of libsec.
 */
PK11Context *
__PK11_CreateContextByRawKey(PK11SlotInfo *slot, CK_MECHANISM_TYPE type,
                             PK11Origin origin, CK_ATTRIBUTE_TYPE operation, SECItem *key,
                             SECItem *param, void *wincx)
{
    PK11SymKey *symKey = NULL;
    PK11Context *context = NULL;

    /* first get a slot */
    if (slot == NULL) {
        slot = PK11_GetBestSlot(type, wincx);
        if (slot == NULL) {
            PORT_SetError(SEC_ERROR_NO_MODULE);
            goto loser;
        }
    } else {
        PK11_ReferenceSlot(slot);
    }

    /* now import the key */
    symKey = PK11_ImportSymKey(slot, type, origin, operation, key, wincx);
    if (symKey == NULL)
        goto loser;

    context = PK11_CreateContextBySymKey(type, operation, symKey, param);

loser:
    if (symKey) {
        PK11_FreeSymKey(symKey);
    }
    if (slot) {
        PK11_FreeSlot(slot);
    }

    return context;
}
Example #13
0
/*
 * NSS_CMSContentInfo_Destroy - destroy a CMS contentInfo and all of its sub-pieces.
 */
void
NSS_CMSContentInfo_Destroy(NSSCMSContentInfo *cinfo)
{
    SECOidTag kind;

    if (cinfo == NULL) {
        return;
    }

    kind = NSS_CMSContentInfo_GetContentTypeTag(cinfo);
    switch (kind) {
        case SEC_OID_PKCS7_ENVELOPED_DATA:
            NSS_CMSEnvelopedData_Destroy(cinfo->content.envelopedData);
            break;
        case SEC_OID_PKCS7_SIGNED_DATA:
            NSS_CMSSignedData_Destroy(cinfo->content.signedData);
            break;
        case SEC_OID_PKCS7_ENCRYPTED_DATA:
            NSS_CMSEncryptedData_Destroy(cinfo->content.encryptedData);
            break;
        case SEC_OID_PKCS7_DIGESTED_DATA:
            NSS_CMSDigestedData_Destroy(cinfo->content.digestedData);
            break;
        default:
            NSS_CMSGenericWrapperData_Destroy(kind, cinfo->content.genericData);
            /* XXX Anything else that needs to be "manually" freed/destroyed? */
            break;
    }
    if (cinfo->privateInfo) {
        nss_cmsContentInfo_private_destroy(cinfo->privateInfo);
        cinfo->privateInfo = NULL;
    }
    if (cinfo->bulkkey) {
        PK11_FreeSymKey(cinfo->bulkkey);
    }
}
Example #14
0
char *
crypto_decrypt (const char *cipher,
                int key_type,
                const guint8 *data,
                gsize data_len,
                const char *iv,
                const gsize iv_len,
                const char *key,
                const gsize key_len,
                gsize *out_len,
                GError **error)
{
	char *output = NULL;
	int decrypted_len = 0;
	CK_MECHANISM_TYPE cipher_mech;
	PK11SlotInfo *slot = NULL;
	SECItem key_item;
	PK11SymKey *sym_key = NULL;
	SECItem *sec_param = NULL;
	PK11Context *ctx = NULL;
	SECStatus s;
	gboolean success = FALSE;
	unsigned int pad_len = 0, extra = 0;
	guint32 i, real_iv_len = 0;

	if (!crypto_init (error))
		return NULL;

	if (!strcmp (cipher, CIPHER_DES_EDE3_CBC)) {
		cipher_mech = CKM_DES3_CBC_PAD;
		real_iv_len = 8;
	} else if (!strcmp (cipher, CIPHER_DES_CBC)) {
		cipher_mech = CKM_DES_CBC_PAD;
		real_iv_len = 8;
	} else if (!strcmp (cipher, CIPHER_AES_CBC)) {
		cipher_mech = CKM_AES_CBC_PAD;
		real_iv_len = 16;
	} else {
		g_set_error (error, NM_CRYPTO_ERROR,
		             NM_CRYPTO_ERROR_UNKNOWN_CIPHER,
		             _("Private key cipher '%s' was unknown."),
		             cipher);
		return NULL;
	}

	if (iv_len < real_iv_len) {
		g_set_error (error, NM_CRYPTO_ERROR,
		             NM_CRYPTO_ERROR_INVALID_DATA,
		             _("Invalid IV length (must be at least %d)."),
		             real_iv_len);
		return NULL;
	}

	output = g_malloc0 (data_len);

	slot = PK11_GetBestSlot (cipher_mech, NULL);
	if (!slot) {
		g_set_error (error, NM_CRYPTO_ERROR,
		             NM_CRYPTO_ERROR_FAILED,
		             _("Failed to initialize the decryption cipher slot."));
		goto out;
	}

	key_item.data = (unsigned char *) key;
	key_item.len = key_len;
	sym_key = PK11_ImportSymKey (slot, cipher_mech, PK11_OriginUnwrap, CKA_DECRYPT, &key_item, NULL);
	if (!sym_key) {
		g_set_error (error, NM_CRYPTO_ERROR,
		             NM_CRYPTO_ERROR_DECRYPTION_FAILED,
		             _("Failed to set symmetric key for decryption."));
		goto out;
	}

	key_item.data = (unsigned char *) iv;
	key_item.len = real_iv_len;
	sec_param = PK11_ParamFromIV (cipher_mech, &key_item);
	if (!sec_param) {
		g_set_error (error, NM_CRYPTO_ERROR,
		             NM_CRYPTO_ERROR_DECRYPTION_FAILED,
		             _("Failed to set IV for decryption."));
		goto out;
	}

	ctx = PK11_CreateContextBySymKey (cipher_mech, CKA_DECRYPT, sym_key, sec_param);
	if (!ctx) {
		g_set_error (error, NM_CRYPTO_ERROR,
		             NM_CRYPTO_ERROR_DECRYPTION_FAILED,
		             _("Failed to initialize the decryption context."));
		goto out;
	}

	s = PK11_CipherOp (ctx,
	                   (unsigned char *) output,
	                   &decrypted_len,
	                   data_len,
	                   data,
	                   data_len);
	if (s != SECSuccess) {
		g_set_error (error, NM_CRYPTO_ERROR,
		             NM_CRYPTO_ERROR_DECRYPTION_FAILED,
		             _("Failed to decrypt the private key: %d."),
		             PORT_GetError ());
		goto out;
	}

	if (decrypted_len > data_len) {
		g_set_error (error, NM_CRYPTO_ERROR,
		             NM_CRYPTO_ERROR_DECRYPTION_FAILED,
		             _("Failed to decrypt the private key: decrypted data too large."));
		goto out;
	}

	s = PK11_DigestFinal (ctx,
	                      (unsigned char *) (output + decrypted_len),
	                      &extra,
	                      data_len - decrypted_len);
	if (s != SECSuccess) {
		g_set_error (error, NM_CRYPTO_ERROR,
		             NM_CRYPTO_ERROR_DECRYPTION_FAILED,
		             _("Failed to finalize decryption of the private key: %d."),
		             PORT_GetError ());
		goto out;
	}
	decrypted_len += extra;
	pad_len = data_len - decrypted_len;

	/* Check if the padding at the end of the decrypted data is valid */
	if (pad_len == 0 || pad_len > real_iv_len) {
		g_set_error (error, NM_CRYPTO_ERROR,
		             NM_CRYPTO_ERROR_DECRYPTION_FAILED,
		             _("Failed to decrypt the private key: unexpected padding length."));
		goto out;
	}

	/* Validate tail padding; last byte is the padding size, and all pad bytes
	 * should contain the padding size.
	 */
	for (i = pad_len; i > 0; i--) {
		if (output[data_len - i] != pad_len) {
			g_set_error (error, NM_CRYPTO_ERROR,
			             NM_CRYPTO_ERROR_DECRYPTION_FAILED,
			             _("Failed to decrypt the private key."));
			goto out;
		}
	}

	*out_len = decrypted_len;
	success = TRUE;

out:
	if (ctx)
		PK11_DestroyContext (ctx, PR_TRUE);
	if (sym_key)
		PK11_FreeSymKey (sym_key);
	if (sec_param)
		SECITEM_FreeItem (sec_param, PR_TRUE);
	if (slot)
		PK11_FreeSlot (slot);

	if (!success) {
		if (output) {
			/* Don't expose key material */
			memset (output, 0, data_len);
			g_free (output);
			output = NULL;
		}
	}
	return output;
}
Example #15
0
/*
 * pk11_getKeyFromList returns a symKey that has a session (if needSession
 * was specified), or explicitly does not have a session (if needSession
 * was not specified).
 */
static PK11SymKey *
pk11_getKeyFromList(PK11SlotInfo *slot, PRBool needSession) {
    PK11SymKey *symKey = NULL;

    PZ_Lock(slot->freeListLock);
    /* own session list are symkeys with sessions that the symkey owns.
     * 'most' symkeys will own their own session. */
    if (needSession) {
	if (slot->freeSymKeysWithSessionHead) {
    	    symKey = slot->freeSymKeysWithSessionHead;
	    slot->freeSymKeysWithSessionHead = symKey->next;
	    slot->keyCount--;
	}
    }
    /* if we don't need a symkey with its own session, or we couldn't find
     * one on the owner list, get one from the non-owner free list. */
    if (!symKey) {
	if (slot->freeSymKeysHead) {
    	    symKey = slot->freeSymKeysHead;
	    slot->freeSymKeysHead = symKey->next;
	    slot->keyCount--;
	}
    }
    PZ_Unlock(slot->freeListLock);
    if (symKey) {
	symKey->next = NULL;
	if (!needSession) {
	    return symKey;
	}
	/* if we are getting an owner key, make sure we have a valid session.
         * session could be invalid if the token has been removed or because
         * we got it from the non-owner free list */
	if ((symKey->series != slot->series) || 
			 (symKey->session == CK_INVALID_SESSION)) {
	    symKey->session = pk11_GetNewSession(slot, &symKey->sessionOwner);
	}
	PORT_Assert(symKey->session != CK_INVALID_SESSION);
	if (symKey->session != CK_INVALID_SESSION)
	    return symKey;
	PK11_FreeSymKey(symKey);
	/* if we are here, we need a session, but couldn't get one, it's 
	 * unlikely we pk11_GetNewSession will succeed if we call it a second
	 * time. */
	return NULL;
    }

    symKey = PORT_New(PK11SymKey);
    if (symKey == NULL) {
	return NULL;
    }

    symKey->next = NULL;
    if (needSession) {
	symKey->session = pk11_GetNewSession(slot,&symKey->sessionOwner);
	PORT_Assert(symKey->session != CK_INVALID_SESSION);
        if (symKey->session == CK_INVALID_SESSION) {
	    PK11_FreeSymKey(symKey);
	    symKey = NULL;
	}
    } else {
	symKey->session = CK_INVALID_SESSION;
    }
    return symKey;
}
Example #16
0
/*
 * destroy a symetric key
 */
void
PK11_FreeSymKey(PK11SymKey *symKey)
{
    PK11SlotInfo *slot;
    PRBool freeit = PR_TRUE;

    if (PR_ATOMIC_DECREMENT(&symKey->refCount) == 0) {
	PK11SymKey *parent = symKey->parent;

	symKey->parent = NULL;
	if ((symKey->owner) && symKey->objectID != CK_INVALID_HANDLE) {
	    pk11_EnterKeyMonitor(symKey);
	    (void) PK11_GETTAB(symKey->slot)->
		C_DestroyObject(symKey->session, symKey->objectID);
	    pk11_ExitKeyMonitor(symKey);
	}
	if (symKey->data.data) {
	    PORT_Memset(symKey->data.data, 0, symKey->data.len);
	    PORT_Free(symKey->data.data);
	}
	/* free any existing data */
	if (symKey->userData && symKey->freeFunc) {
	    (*symKey->freeFunc)(symKey->userData);
	}
        slot = symKey->slot;
        PZ_Lock(slot->freeListLock);
	if (slot->keyCount < slot->maxKeyCount) {
	    /* 
             * freeSymkeysWithSessionHead contain a list of reusable
	     *  SymKey structures with valid sessions.
	     *    sessionOwner must be true.
             *    session must be valid.
             * freeSymKeysHead contain a list of SymKey structures without
             *  valid session.
             *    session must be CK_INVALID_SESSION.
	     *    though sessionOwner is false, callers should not depend on
	     *    this fact.
	     */
	    if (symKey->sessionOwner) {
		PORT_Assert (symKey->session != CK_INVALID_SESSION);
		symKey->next = slot->freeSymKeysWithSessionHead;
		slot->freeSymKeysWithSessionHead = symKey;
	    } else {
		symKey->session = CK_INVALID_SESSION;
		symKey->next = slot->freeSymKeysHead;
		slot->freeSymKeysHead = symKey;
	    }
	    slot->keyCount++;
	    symKey->slot = NULL;
	    freeit = PR_FALSE;
        }
	PZ_Unlock(slot->freeListLock);
        if (freeit) {
	    pk11_CloseSession(symKey->slot, symKey->session,
							symKey->sessionOwner);
	    PORT_Free(symKey);
	}
	PK11_FreeSlot(slot);

	if (parent) {
	    PK11_FreeSymKey(parent);
	}
    }
}
Example #17
0
void
hmac_init(struct hmac_ctx *ctx,
    const struct hash_desc *h,
    const u_char *key, size_t key_len)
{
#ifndef HAVE_LIBNSS
    int k;
#endif
    ctx->h = h;
    ctx->hmac_digest_len = h->hash_digest_len;

#ifdef HAVE_LIBNSS
    /* DBG(DBG_CRYPT, DBG_log("NSS: hmac init")); */
    SECStatus status;
    PK11SymKey *symkey=NULL, *tkey1=NULL;
    /* PK11SymKey *tkey1=NULL; */
    unsigned int klen;
    chunk_t hmac_opad, hmac_ipad, hmac_pad;

    memcpy(&symkey, key, key_len);
    klen =  PK11_GetKeyLength(symkey);

    hmac_opad = hmac_pads(HMAC_OPAD,HMAC_BUFSIZE);
    hmac_ipad = hmac_pads(HMAC_IPAD,HMAC_BUFSIZE);
    hmac_pad  = hmac_pads(0x00,HMAC_BUFSIZE-klen);

    if(klen > HMAC_BUFSIZE)
    {
	tkey1 = PK11_Derive_osw(symkey, nss_key_derivation_mech(h)
				, NULL, CKM_CONCATENATE_BASE_AND_DATA, CKA_DERIVE, 0);
    }
    else
    {
	tkey1 = symkey;
    }

    PK11SymKey *tkey2 = pk11_derive_wrapper_osw(tkey1, CKM_CONCATENATE_BASE_AND_DATA
				, hmac_pad,CKM_XOR_BASE_AND_DATA, CKA_DERIVE, HMAC_BUFSIZE);

    PR_ASSERT(tkey2!=NULL);
    ctx->ikey = pk11_derive_wrapper_osw(tkey2, CKM_XOR_BASE_AND_DATA
					, hmac_ipad,nss_hash_mech(h), CKA_DIGEST, 0);

    PR_ASSERT(ctx->ikey !=NULL);
    ctx->okey = pk11_derive_wrapper_osw(tkey2, CKM_XOR_BASE_AND_DATA
					, hmac_opad,nss_hash_mech(h), CKA_DIGEST, 0);

    PR_ASSERT(ctx->okey !=NULL);

    if(tkey1!=symkey) {
	PK11_FreeSymKey(tkey1);
    }
    PK11_FreeSymKey(tkey2);

    freeanychunk(hmac_opad);
    freeanychunk(hmac_ipad);
    freeanychunk(hmac_pad);
    ctx->ctx_nss = PK11_CreateDigestContext(nss_hash_oid(h));
    PR_ASSERT(ctx->ctx_nss!=NULL);

    status=PK11_DigestBegin(ctx->ctx_nss);
    PR_ASSERT(status==SECSuccess);

    status=PK11_DigestKey(ctx->ctx_nss, ctx->ikey);
    PR_ASSERT(status==SECSuccess);

#else

    /* Prepare the two pads for the HMAC */

    memset(ctx->buf1, '\0', HMAC_BUFSIZE);

    if (key_len <= HMAC_BUFSIZE)
    {
	memcpy(ctx->buf1, key, key_len);
    }
    else
    {
	h->hash_init(&ctx->hash_ctx);
	h->hash_update(&ctx->hash_ctx, key, key_len);
	h->hash_final(ctx->buf1, &ctx->hash_ctx);
    }

    memcpy(ctx->buf2, ctx->buf1, HMAC_BUFSIZE);

    for (k = 0; k < HMAC_BUFSIZE; k++)
    {
	ctx->buf1[k] ^= HMAC_IPAD;
	ctx->buf2[k] ^= HMAC_OPAD;
    }

    hmac_reinit(ctx);
#endif
}
Example #18
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;
}
Example #19
0
static SECStatus
aes_decrypt_buf(
    const unsigned char *key, unsigned int keysize,
    const unsigned char *iv, unsigned int ivsize,
    unsigned char *output, unsigned int *outputlen, unsigned int maxoutputlen,
    const unsigned char *input, unsigned int inputlen,
    const unsigned char *aad, unsigned int aadlen,
    const unsigned char *tag, unsigned int tagsize)
{
    SECStatus rv = SECFailure;
    unsigned char concatenated[11*16];     /* 1 to 11 blocks */
    SECItem key_item;
    PK11SlotInfo *slot = NULL;
    PK11SymKey *symKey = NULL;
    CK_GCM_PARAMS gcm_params;
    SECItem param;

    if (inputlen + tagsize > sizeof(concatenated)) {
	fprintf(stderr, "aes_decrypt_buf: local buffer too small\n");
	goto loser;
    }
    memcpy(concatenated, input, inputlen);
    memcpy(concatenated + inputlen, tag, tagsize);

    /* Import key into NSS. */
    key_item.type = siBuffer;
    key_item.data = (unsigned char *) key;  /* const cast */
    key_item.len = keysize;
    slot = PK11_GetInternalSlot();
    symKey = PK11_ImportSymKey(slot, CKM_AES_GCM, PK11_OriginUnwrap,
			       CKA_DECRYPT, &key_item, NULL);
    PK11_FreeSlot(slot);
    slot = NULL;
    if (!symKey) {
	fprintf(stderr, "PK11_ImportSymKey failed\n");
	goto loser;
    }

    gcm_params.pIv = (unsigned char *) iv;
    gcm_params.ulIvLen = ivsize;
    gcm_params.pAAD = (unsigned char *) aad;
    gcm_params.ulAADLen = aadlen;
    gcm_params.ulTagBits = tagsize * 8;

    param.type = siBuffer;
    param.data = (unsigned char *) &gcm_params;
    param.len = sizeof(gcm_params);

    if (PK11_Decrypt(symKey, CKM_AES_GCM, &param,
		     output, outputlen, maxoutputlen,
		     concatenated, inputlen + tagsize) != SECSuccess) {
	goto loser;
    }

    rv = SECSuccess;

loser:
    if (symKey != NULL) {
	PK11_FreeSymKey(symKey);
    }
    return rv;
}
Example #20
0
int main(int argc, char **argv)
{
  CK_MECHANISM_TYPE  hashMech;
  PK11SlotInfo*      slot = NULL;
  PK11SymKey*        SymKey = NULL;
  SECItem            SecParam;
  PK11Context*       HashContext = NULL;
  SECItem            keyItem;
  SECStatus          rv, rv1, rv2;
  unsigned char      buf1[1024], buf2[1024];
  char		     data[1024];
  int                i;
  unsigned int       tmp2_outlen;

  /* Initialize NSS
 *    * If your application code has already initialized NSS, you can skip it
 *       * here.
 *          * This code uses the simplest of the Init functions, which does not
 *             * require a NSS database to exist
 *                */
  rv = NSS_NoDB_Init(".");
  if (rv != SECSuccess)
  {
    fprintf(stderr, "NSS initialization failed (err %d)\n",
            PR_GetError());
    goto out;
  }

  /* choose mechanism: CKM_DES_CBC_PAD, CKM_DES3_ECB, CKM_DES3_CBC..... 
 *    * Note that some mechanisms (*_PAD) imply the padding is handled for you
 *       * by NSS. If you choose something else, then data padding is the
 *          * application's responsibility
 *             */
  hashMech = CKM_SHA_1_HMAC;
  slot = PK11_GetBestSlot(hashMech, NULL);
  /* slot = PK11_GetInternalKeySlot(); is a simpler alternative but in
 *    * theory, it *may not* return the optimal slot for the operation. For
 *       * DES ops, Internal slot is typically the best slot
 *          */
  if (slot == NULL)
  {
    fprintf(stderr, "Unable to find security device (err %d)\n",
            PR_GetError());
    goto out;
  }

  /* NSS passes blobs around as SECItems. These contain a pointer to
 *    * data and a length. Turn the raw key into a SECItem. */
  keyItem.type = siBuffer;
  keyItem.data = gKey;
  keyItem.len = sizeof(gKey);

  /* Turn the raw key into a key object. We use PK11_OriginUnwrap
 *    * to indicate the key was unwrapped - which is what should be done
 *       * normally anyway - using raw keys isn't a good idea */
  SymKey = PK11_ImportSymKey(slot, hashMech, PK11_OriginUnwrap, CKA_SIGN,
                             &keyItem, NULL);
  if (SymKey == NULL)
  {
    fprintf(stderr, "Failure to import key into NSS (err %d)\n",
            PR_GetError());
    goto out;
  }

  SecParam.type = siBuffer;
  SecParam.data = 0;
  SecParam.len = 0;

  /* sample data we'll hash */
  strcpy(data, "Hash me!");
  fprintf(stderr, "Clear Data: %s\n", data);

  /* ========================= START SECTION ============================= */
  /* If using the the same key and iv over and over, stuff before this     */
  /* section and after this section needs to be done only ONCE             */

  /* Create cipher context */
  HashContext = PK11_CreateContextBySymKey(hashMech, CKA_SIGN,
                                          SymKey, &SecParam);

  if (!HashContext) {
    fprintf(stderr, "no hash context today?\n");
    goto out;
  }

  if (PK11_DigestBegin(HashContext) != SECSuccess) {
    fprintf(stderr, "hash doesn't begin?\n");
    goto out;
  }

  rv1 = PK11_DigestOp(HashContext, (unsigned char *)data, strlen(data)+1);

  rv2 = PK11_DigestFinal(HashContext, buf2, &tmp2_outlen, SHA1_BLOCK_LENGTH);

  PK11_DestroyContext(HashContext, PR_TRUE);
  if (rv1 != SECSuccess || rv2 != SECSuccess)
    goto out;

  fprintf(stderr, "Hash Data: ");
  for (i=0; i<tmp2_outlen; i++)
    fprintf(stderr, "%02x ", buf2[i]);
  fprintf(stderr, "\n");

  /* =========================== END SECTION ============================= */

  /* ========================= START SECTION ============================= */
  /* If using the the same key and iv over and over, stuff before this     */
  /* section and after this section needs to be done only ONCE             */

  memset(buf1, 0, sizeof(buf1));
  memset(buf2, 0, sizeof(buf2));

  /* Create cipher context */
  HashContext = PK11_CreateContextBySymKey(hashMech, CKA_SIGN,
                                          SymKey, &SecParam);

  if (!HashContext) {
    fprintf(stderr, "no hash context today?\n");
    goto out;
  }

  if (PK11_DigestBegin(HashContext) != SECSuccess) {
    fprintf(stderr, "hash doesn't begin?\n");
    goto out;
  }

  rv1 = PK11_DigestOp(HashContext, (unsigned char *)data, 5);
  rv1 = PK11_DigestOp(HashContext, (unsigned char *)data+5, 4);

  rv2 = PK11_DigestFinal(HashContext, buf2, &tmp2_outlen, SHA1_BLOCK_LENGTH);

  PK11_DestroyContext(HashContext, PR_TRUE);
  if (rv1 != SECSuccess || rv2 != SECSuccess)
    goto out;

  fprintf(stderr, "Hash Data: ");
  for (i=0; i<tmp2_outlen; i++)
    fprintf(stderr, "%02x ", buf2[i]);
  fprintf(stderr, "\n");

  /* =========================== END SECTION ============================= */

 
out:
  if (SymKey)
    PK11_FreeSymKey(SymKey);

 return 0;

}
Example #21
0
/*
 * Digest a key if possible./
 */
SECStatus
PK11_DigestKey(PK11Context *context, PK11SymKey *key)
{
    CK_RV crv = CKR_OK;
    SECStatus rv = SECSuccess;
    PK11SymKey *newKey = NULL;

    if (!context || !key) {
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
        return SECFailure;
    }

    /* if we ran out of session, we need to restore our previously stored
     * state.
     */
    if (context->slot != key->slot) {
        newKey = pk11_CopyToSlot(context->slot,CKM_SSL3_SHA1_MAC,CKA_SIGN,key);
    } else {
        newKey = PK11_ReferenceSymKey(key);
    }

    context->init = PR_FALSE;
    PK11_EnterContextMonitor(context);
    if (!context->ownSession) {
        rv = pk11_restoreContext(context,context->savedData,
                                 context->savedLength);
        if (rv != SECSuccess) {
            PK11_ExitContextMonitor(context);
            PK11_FreeSymKey(newKey);
            return rv;
        }
    }


    if (newKey == NULL) {
        crv = CKR_KEY_TYPE_INCONSISTENT;
        if (key->data.data) {
            crv=PK11_GETTAB(context->slot)->C_DigestUpdate(context->session,
                    key->data.data,key->data.len);
        }
    } else {
        crv=PK11_GETTAB(context->slot)->C_DigestKey(context->session,
                newKey->objectID);
    }

    if (crv != CKR_OK) {
        PORT_SetError( PK11_MapError(crv) );
        rv = SECFailure;
    }

    /*
     * handle session starvation case.. use our last session to multiplex
     */
    if (!context->ownSession) {
        context->savedData = pk11_saveContext(context,context->savedData,
                                              &context->savedLength);
        if (context->savedData == NULL) rv = SECFailure;

        /* clear out out session for others to use */
        pk11_Finalize(context);
    }
    PK11_ExitContextMonitor(context);
    if (newKey) PK11_FreeSymKey(newKey);
    return rv;
}
Example #22
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;
    const namedGroupDef *groupDef;
    sslEphemeralKeyPair *keyPair = NULL;
    SECKEYPublicKey *pubKey;

    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;
    }
    groupDef = ssl_ECPubKey2NamedGroup(svrPubKey);
    if (!groupDef) {
        PORT_SetError(SEC_ERROR_BAD_KEY);
        goto loser;
    }
    rv = ssl_CreateECDHEphemeralKeyPair(groupDef, &keyPair);
    if (rv != SECSuccess) {
        ssl_MapLowLevelError(SEC_ERROR_KEYGEN_FAIL);
        goto loser;
    }

    pubKey = keyPair->keys->pubKey;
    PRINT_BUF(50, (ss, "ECDH public value:",
                   pubKey->u.ec.publicValue.data,
                   pubKey->u.ec.publicValue.len));

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

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

    if (pms == NULL) {
        (void)SSL3_SendAlert(ss, alert_fatal, illegal_parameter);
        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);

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

    rv = ssl3_InitPendingCipherSpec(ss, pms);
    if (rv != SECSuccess) {
        ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE);
        goto loser;
    }

    PK11_FreeSymKey(pms);
    ssl_FreeEphemeralKeyPair(keyPair);
    return SECSuccess;

loser:
    if (pms)
        PK11_FreeSymKey(pms);
    if (keyPair)
        ssl_FreeEphemeralKeyPair(keyPair);
    return SECFailure;
}
Example #23
0
SECStatus
tls13_HkdfExtract(PK11SymKey *ikm1, PK11SymKey *ikm2in, SSLHashType baseHash,
                  PK11SymKey **prkp)
{
    CK_NSS_HKDFParams params;
    SECItem paramsi;
    SECStatus rv;
    SECItem *salt;
    PK11SymKey *prk;
    static const PRUint8 zeroKeyBuf[HASH_LENGTH_MAX];
    PK11SymKey *zeroKey = NULL;
    PK11SlotInfo *slot = NULL;
    PK11SymKey *ikm2;

    params.bExtract = CK_TRUE;
    params.bExpand = CK_FALSE;
    params.pInfo = NULL;
    params.ulInfoLen = 0UL;

    if (ikm1) {
        /* TODO([email protected]): This violates the PKCS#11 key boundary
         * but is imposed on us by the present HKDF interface. */
        rv = PK11_ExtractKeyValue(ikm1);
        if (rv != SECSuccess)
            return rv;

        salt = PK11_GetKeyData(ikm1);
        if (!salt)
            return SECFailure;

        params.pSalt = salt->data;
        params.ulSaltLen = salt->len;
        PORT_Assert(salt->len > 0);
    } else {
        /* Per documentation for CKM_NSS_HKDF_*:
         *
         *  If the optional salt is given, it is used; otherwise, the salt is
         *  set to a sequence of zeros equal in length to the HMAC output.
         */
        params.pSalt = NULL;
        params.ulSaltLen = 0UL;
    }
    paramsi.data = (unsigned char *)&params;
    paramsi.len = sizeof(params);

    PORT_Assert(kTlsHkdfInfo[baseHash].pkcs11Mech);
    PORT_Assert(kTlsHkdfInfo[baseHash].hashSize);
    PORT_Assert(kTlsHkdfInfo[baseHash].hash == baseHash);

    /* A zero ikm2 is a key of hash-length 0s. */
    if (!ikm2in) {
        SECItem zeroItem = {
            siBuffer,
            (unsigned char *)zeroKeyBuf,
            kTlsHkdfInfo[baseHash].hashSize
        };
        slot = PK11_GetInternalSlot();
        if (!slot) {
            return SECFailure;
        }
        zeroKey = PK11_ImportSymKey(slot,
                                    kTlsHkdfInfo[baseHash].pkcs11Mech,
                                    PK11_OriginUnwrap,
                                    CKA_DERIVE, &zeroItem, NULL);
        if (!zeroKey)
            return SECFailure;
        ikm2 = zeroKey;
    } else {
        ikm2 = ikm2in;
    }
    PORT_Assert(ikm2);

    PRINT_BUF(50, (NULL, "HKDF Extract: IKM1/Salt", params.pSalt, params.ulSaltLen));
    PRINT_KEY(50, (NULL, "HKDF Extract: IKM2", ikm2));

    prk = PK11_Derive(ikm2, kTlsHkdfInfo[baseHash].pkcs11Mech,
                      &paramsi, kTlsHkdfInfo[baseHash].pkcs11Mech,
                      CKA_DERIVE, kTlsHkdfInfo[baseHash].hashSize);
    if (zeroKey)
        PK11_FreeSymKey(zeroKey);
    if (slot)
        PK11_FreeSlot(slot);
    if (!prk)
        return SECFailure;

    PRINT_KEY(50, (NULL, "HKDF Extract", prk));
    *prkp = prk;

    return SECSuccess;
}
Example #24
0
char *
crypto_encrypt (const char *cipher,
                const guint8 *data,
                gsize data_len,
                const char *iv,
                gsize iv_len,
                const char *key,
                gsize key_len,
                gsize *out_len,
                GError **error)
{
	SECStatus ret;
	CK_MECHANISM_TYPE cipher_mech = CKM_DES3_CBC_PAD;
	PK11SlotInfo *slot = NULL;
	SECItem key_item = { .data = (unsigned char *) key, .len = key_len };
	SECItem iv_item = { .data = (unsigned char *) iv, .len = iv_len };
	PK11SymKey *sym_key = NULL;
	SECItem *sec_param = NULL;
	PK11Context *ctx = NULL;
	unsigned char *output, *padded_buf;
	gsize output_len;
	int encrypted_len = 0, i;
	gboolean success = FALSE;
	gsize padded_buf_len, pad_len;

	if (!crypto_init (error))
		return NULL;

	if (!strcmp (cipher, CIPHER_DES_EDE3_CBC))
		cipher_mech = CKM_DES3_CBC_PAD;
	else if (!strcmp (cipher, CIPHER_AES_CBC))
		cipher_mech = CKM_AES_CBC_PAD;
	else {
		g_set_error (error, NM_CRYPTO_ERROR,
		             NM_CRYPTO_ERROR_UNKNOWN_CIPHER,
		             _("Private key cipher '%s' was unknown."),
		             cipher);
		return NULL;
	}

	/* If data->len % ivlen == 0, then we add another complete block
	 * onto the end so that the decrypter knows there's padding.
	 */
	pad_len = iv_len - (data_len % iv_len);
	output_len = padded_buf_len = data_len + pad_len;
	padded_buf = g_malloc0 (padded_buf_len);

	memcpy (padded_buf, data, data_len);
	for (i = 0; i < pad_len; i++)
		padded_buf[data_len + i] = (guint8) (pad_len & 0xFF);

	output = g_malloc0 (output_len);

	slot = PK11_GetBestSlot (cipher_mech, NULL);
	if (!slot) {
		g_set_error (error, NM_CRYPTO_ERROR,
		             NM_CRYPTO_ERROR_FAILED,
		             _("Failed to initialize the encryption cipher slot."));
		goto out;
	}

	sym_key = PK11_ImportSymKey (slot, cipher_mech, PK11_OriginUnwrap, CKA_ENCRYPT, &key_item, NULL);
	if (!sym_key) {
		g_set_error (error, NM_CRYPTO_ERROR,
		             NM_CRYPTO_ERROR_ENCRYPTION_FAILED,
		             _("Failed to set symmetric key for encryption."));
		goto out;
	}

	sec_param = PK11_ParamFromIV (cipher_mech, &iv_item);
	if (!sec_param) {
		g_set_error (error, NM_CRYPTO_ERROR,
		             NM_CRYPTO_ERROR_ENCRYPTION_FAILED,
		             _("Failed to set IV for encryption."));
		goto out;
	}

	ctx = PK11_CreateContextBySymKey (cipher_mech, CKA_ENCRYPT, sym_key, sec_param);
	if (!ctx) {
		g_set_error (error, NM_CRYPTO_ERROR,
		             NM_CRYPTO_ERROR_ENCRYPTION_FAILED,
		             _("Failed to initialize the encryption context."));
		goto out;
	}

	ret = PK11_CipherOp (ctx, output, &encrypted_len, output_len, padded_buf, padded_buf_len);
	if (ret != SECSuccess) {
		g_set_error (error, NM_CRYPTO_ERROR,
		             NM_CRYPTO_ERROR_ENCRYPTION_FAILED,
		             _("Failed to encrypt: %d."),
		             PORT_GetError ());
		goto out;
	}

	if (encrypted_len != output_len) {
		g_set_error (error, NM_CRYPTO_ERROR,
		             NM_CRYPTO_ERROR_ENCRYPTION_FAILED,
		             _("Unexpected amount of data after encrypting."));
		goto out;
	}

	*out_len = encrypted_len;
	success = TRUE;

out:
	if (ctx)
		PK11_DestroyContext (ctx, PR_TRUE);
	if (sym_key)
		PK11_FreeSymKey (sym_key);
	if (sec_param)
		SECITEM_FreeItem (sec_param, PR_TRUE);
	if (slot)
		PK11_FreeSlot (slot);

	memset (padded_buf, 0, padded_buf_len);
	g_free (padded_buf);

	if (!success) {
		memset (output, 0, output_len);
		g_free (output);
		output = NULL;
	}
	return (char *) output;
}

NMCryptoFileFormat
crypto_verify_cert (const unsigned char *data,
                    gsize len,
                    GError **error)
{
	CERTCertificate *cert;

	if (!crypto_init (error))
		return NM_CRYPTO_FILE_FORMAT_UNKNOWN;

	/* Try DER/PEM first */
	cert = CERT_DecodeCertFromPackage ((char *) data, len);
	if (!cert) {
		g_set_error (error, NM_CRYPTO_ERROR,
		             NM_CRYPTO_ERROR_INVALID_DATA,
		             _("Couldn't decode certificate: %d"),
		             PORT_GetError());
		return NM_CRYPTO_FILE_FORMAT_UNKNOWN;
	}

	CERT_DestroyCertificate (cert);
	return NM_CRYPTO_FILE_FORMAT_X509;
}

gboolean
crypto_verify_pkcs12 (const guint8 *data,
                      gsize data_len,
                      const char *password,
                      GError **error)
{
	SEC_PKCS12DecoderContext *p12ctx = NULL;
	SECItem pw = { 0 };
	PK11SlotInfo *slot = NULL;
	SECStatus s;
	gunichar2 *ucs2_password;
	glong ucs2_chars = 0;
#ifndef WORDS_BIGENDIAN
	guint16 *p;
#endif /* WORDS_BIGENDIAN */

	if (error)
		g_return_val_if_fail (*error == NULL, FALSE);

	if (!crypto_init (error))
		return FALSE;

	/* PKCS#12 passwords are apparently UCS2 BIG ENDIAN, and NSS doesn't do
	 * any conversions for us.
	 */
	if (password && *password) {
		if (!g_utf8_validate (password, -1, NULL)) {
			g_set_error (error, NM_CRYPTO_ERROR,
			             NM_CRYPTO_ERROR_INVALID_PASSWORD,
			             _("Password must be UTF-8"));
			return FALSE;
		}
		ucs2_password = g_utf8_to_utf16 (password, strlen (password), NULL, &ucs2_chars, NULL);
		/* Can't fail if g_utf8_validate() succeeded */
		g_return_val_if_fail (ucs2_password != NULL && ucs2_chars != 0, FALSE);

		ucs2_chars *= 2;  /* convert # UCS2 characters -> bytes */
		pw.data = PORT_ZAlloc(ucs2_chars + 2);
		memcpy (pw.data, ucs2_password, ucs2_chars);
		pw.len = ucs2_chars + 2;  /* include terminating NULL */

		memset (ucs2_password, 0, ucs2_chars);
		g_free (ucs2_password);

#ifndef WORDS_BIGENDIAN
		for (p = (guint16 *) pw.data; p < (guint16 *) (pw.data + pw.len); p++)
			*p = GUINT16_SWAP_LE_BE (*p);
#endif /* WORDS_BIGENDIAN */
	} else {
		/* NULL password */
		pw.data = NULL;
		pw.len = 0;
	}

	slot = PK11_GetInternalKeySlot();
	p12ctx = SEC_PKCS12DecoderStart (&pw, slot, NULL, NULL, NULL, NULL, NULL, NULL);
	if (!p12ctx) {
		g_set_error (error, NM_CRYPTO_ERROR,
		             NM_CRYPTO_ERROR_FAILED,
		             _("Couldn't initialize PKCS#12 decoder: %d"),
		             PORT_GetError());
		goto error;
	}

	s = SEC_PKCS12DecoderUpdate (p12ctx, (guint8 *)data, data_len);
	if (s != SECSuccess) {
		g_set_error (error, NM_CRYPTO_ERROR,
		             NM_CRYPTO_ERROR_INVALID_DATA,
		             _("Couldn't decode PKCS#12 file: %d"),
		             PORT_GetError());
		goto error;
	}

	s = SEC_PKCS12DecoderVerify (p12ctx);
	if (s != SECSuccess) {
		g_set_error (error, NM_CRYPTO_ERROR,
		             NM_CRYPTO_ERROR_DECRYPTION_FAILED,
		             _("Couldn't verify PKCS#12 file: %d"),
		             PORT_GetError());
		goto error;
	}

	SEC_PKCS12DecoderFinish (p12ctx);
	SECITEM_ZfreeItem (&pw, PR_FALSE);
	return TRUE;

error:
	if (p12ctx)
		SEC_PKCS12DecoderFinish (p12ctx);

	if (slot)
		PK11_FreeSlot(slot);

	SECITEM_ZfreeItem (&pw, PR_FALSE);
	return FALSE;
}
Example #25
0
static int
sm_encrypt(CamelCipherContext *context, const char *userid, GPtrArray *recipients, CamelMimePart *ipart, CamelMimePart *opart, CamelException *ex)
{
	struct _CamelSMIMEContextPrivate *p = ((CamelSMIMEContext *)context)->priv;
	/*NSSCMSRecipientInfo **recipient_infos;*/
	CERTCertificate **recipient_certs = NULL;
	NSSCMSContentInfo *cinfo;
	PK11SymKey *bulkkey = NULL;
	SECOidTag bulkalgtag;
	int bulkkeysize, i;
	CK_MECHANISM_TYPE type;
	PK11SlotInfo *slot;
	PLArenaPool *poolp;
	NSSCMSMessage *cmsg = NULL;
	NSSCMSEnvelopedData *envd;
 	NSSCMSEncoderContext *enc = NULL;
	CamelStreamMem *mem;
	CamelStream *ostream = NULL;
	CamelDataWrapper *dw;
	CamelContentType *ct;

	poolp = PORT_NewArena(1024);
	if (poolp == NULL) {
		camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, g_strerror (ENOMEM));
		return -1;
	}

	/* Lookup all recipients certs, for later working */
	recipient_certs = (CERTCertificate **)PORT_ArenaZAlloc(poolp, sizeof(*recipient_certs[0])*(recipients->len + 1));
	if (recipient_certs == NULL) {
		camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, g_strerror (ENOMEM));
		goto fail;
	}

	for (i=0;i<recipients->len;i++) {
		recipient_certs[i] = CERT_FindCertByNicknameOrEmailAddr(p->certdb, recipients->pdata[i]);
		if (recipient_certs[i] == NULL) {
			camel_exception_setv(ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot find certificate for `%s'"), recipients->pdata[i]);
			goto fail;
		}
	}

	/* Find a common algorithm, probably 3DES anyway ... */
	if (NSS_SMIMEUtil_FindBulkAlgForRecipients(recipient_certs, &bulkalgtag, &bulkkeysize) != SECSuccess) {
		camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot find common bulk encryption algorithm"));
		goto fail;
	}

	/* Generate a new bulk key based on the common algorithm - expensive */
	type = PK11_AlgtagToMechanism(bulkalgtag);
	slot = PK11_GetBestSlot(type, context);
	if (slot == NULL) {
		/* PORT_GetError(); ?? */
		camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot allocate slot for encryption bulk key"));
		goto fail;
	}

	bulkkey = PK11_KeyGen(slot, type, NULL, bulkkeysize/8, context);
	PK11_FreeSlot(slot);

	/* Now we can start building the message */
	/* msg->envelopedData->data */
	cmsg = NSS_CMSMessage_Create(NULL);
	if (cmsg == NULL) {
		camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot create CMS Message"));
		goto fail;
	}

	envd = NSS_CMSEnvelopedData_Create(cmsg, bulkalgtag, bulkkeysize);
	if (envd == NULL) {
		camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot create CMS Enveloped data"));
		goto fail;
	}

	cinfo = NSS_CMSMessage_GetContentInfo(cmsg);
	if (NSS_CMSContentInfo_SetContent_EnvelopedData(cmsg, cinfo, envd) != SECSuccess) {
		camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot attach CMS Enveloped data"));
		goto fail;
	}

	cinfo = NSS_CMSEnvelopedData_GetContentInfo(envd);
	if (NSS_CMSContentInfo_SetContent_Data(cmsg, cinfo, NULL, PR_FALSE) != SECSuccess) {
		camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot attach CMS data object"));
		goto fail;
	}

	/* add recipient certs */
	for (i=0;recipient_certs[i];i++) {
		NSSCMSRecipientInfo *ri = NSS_CMSRecipientInfo_Create(cmsg, recipient_certs[i]);

		if (ri == NULL) {
			camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot create CMS Recipient information"));
			goto fail;
		}

		if (NSS_CMSEnvelopedData_AddRecipient(envd, ri) != SECSuccess) {
			camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot add CMS Recipient information"));
			goto fail;
		}
	}

	/* dump it out */
	ostream = camel_stream_mem_new();
	enc = NSS_CMSEncoder_Start(cmsg,
				   sm_write_stream, ostream,
				   NULL, NULL,
				   NULL, NULL,
				   sm_decrypt_key, bulkkey,
				   NULL, NULL);
	if (enc == NULL) {
		camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Cannot create encoder context"));
		goto fail;
	}

	/* FIXME: Stream the input */
	/* FIXME: Canonicalise the input? */
	mem = (CamelStreamMem *)camel_stream_mem_new();
	camel_data_wrapper_write_to_stream((CamelDataWrapper *)ipart, (CamelStream *)mem);
	if (NSS_CMSEncoder_Update(enc, (char *) mem->buffer->data, mem->buffer->len) != SECSuccess) {
		NSS_CMSEncoder_Cancel(enc);
		camel_object_unref(mem);
		camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Failed to add data to encoder"));
		goto fail;
	}
	camel_object_unref(mem);

	if (NSS_CMSEncoder_Finish(enc) != SECSuccess) {
		camel_exception_set (ex, CAMEL_EXCEPTION_SYSTEM, _("Failed to encode data"));
		goto fail;
	}

	PK11_FreeSymKey(bulkkey);
	NSS_CMSMessage_Destroy(cmsg);
	for (i=0;recipient_certs[i];i++)
		CERT_DestroyCertificate(recipient_certs[i]);
	PORT_FreeArena(poolp, PR_FALSE);

	dw = camel_data_wrapper_new();
	camel_data_wrapper_construct_from_stream(dw, ostream);
	camel_object_unref(ostream);
	dw->encoding = CAMEL_TRANSFER_ENCODING_BINARY;

	ct = camel_content_type_new("application", "x-pkcs7-mime");
	camel_content_type_set_param(ct, "name", "smime.p7m");
	camel_content_type_set_param(ct, "smime-type", "enveloped-data");
	camel_data_wrapper_set_mime_type_field(dw, ct);
	camel_content_type_unref(ct);

	camel_medium_set_content_object((CamelMedium *)opart, dw);
	camel_object_unref(dw);

	camel_mime_part_set_disposition(opart, "attachment");
	camel_mime_part_set_filename(opart, "smime.p7m");
	camel_mime_part_set_description(opart, "S/MIME Encrypted Message");
	camel_mime_part_set_encoding(opart, CAMEL_TRANSFER_ENCODING_BASE64);

	return 0;

fail:
	if (ostream)
		camel_object_unref(ostream);
	if (cmsg)
		NSS_CMSMessage_Destroy(cmsg);
	if (bulkkey)
		PK11_FreeSymKey(bulkkey);

	if (recipient_certs) {
		for (i=0;recipient_certs[i];i++)
			CERT_DestroyCertificate(recipient_certs[i]);
	}

	PORT_FreeArena(poolp, PR_FALSE);

	return -1;
}
Example #26
0
static int  	
xmlSecNssKWAesOp(const xmlSecByte *key, xmlSecSize keySize,
		 const xmlSecByte *in, xmlSecSize inSize,
		 xmlSecByte *out, xmlSecSize outSize, int enc) {
    xmlSecByte block[XMLSEC_NSS_AES_BLOCK_SIZE];
    xmlSecByte *p;
    int N, i, j, t;
    int result = -1;
    PK11SymKey *aeskey = NULL;
    
    xmlSecAssert2(key != NULL, -1);
    xmlSecAssert2(keySize > 0, -1);
    xmlSecAssert2(in != NULL, -1);
    xmlSecAssert2(inSize > 0, -1);
    xmlSecAssert2(out != NULL, -1);
    xmlSecAssert2(outSize >= inSize + 8, -1);

    if (enc == 1) {
        aeskey = xmlSecNssMakeAesKey(key, keySize, enc);
        if(aeskey == NULL) {
    	    xmlSecErr_a_ignorar5(XMLSEC_ERRORS_HERE, 
    	    	        NULL,
    		        "xmlSecNssMakeAesKey",
    		        XMLSEC_ERRORS_R_CRYPTO_FAILED,
    		        XMLSEC_ERRORS_NO_MESSAGE);
	    goto done;
        }
    
        /* prepend magic block */
        if(in != out) {
            memcpy(out + XMLSEC_NSS_KW_AES_MAGIC_BLOCK_SIZE, in, inSize);
        } else {
            memmove(out + XMLSEC_NSS_KW_AES_MAGIC_BLOCK_SIZE, out, inSize);
        }
        memcpy(out, xmlSecNssKWAesMagicBlock, XMLSEC_NSS_KW_AES_MAGIC_BLOCK_SIZE);
        
        N = (inSize / 8);
        if(N == 1) {
            xmlSecNssAesOp(aeskey, out, out, enc);
        } else {
    	    for(j = 0; j <= 5; ++j) {
    	        for(i = 1; i <= N; ++i) {
    		    t = i + (j * N);
    		    p = out + i * 8;
    
    		    memcpy(block, out, 8);
    		    memcpy(block + 8, p, 8);
    		
                    xmlSecNssAesOp(aeskey, block, block, enc);
    		    block[7] ^=  t;
    		    memcpy(out, block, 8);
    		    memcpy(p, block + 8, 8);
    	        }
    	    }
        }
        
        result = inSize + 8;
    } else {
        aeskey = xmlSecNssMakeAesKey(key, keySize, enc);
        if(aeskey == NULL) {
    	    xmlSecErr_a_ignorar5(XMLSEC_ERRORS_HERE, 
    		        NULL,
    		        "xmlSecNssMakeAesKey",
    		        XMLSEC_ERRORS_R_CRYPTO_FAILED,
    		        XMLSEC_ERRORS_NO_MESSAGE);
	    goto done;
        }
        
        /* copy input */
        if(in != out) {
            memcpy(out, in, inSize);
        }
            
        N = (inSize / 8) - 1;
        if(N == 1) {
            xmlSecNssAesOp(aeskey, out, out, enc);
        } else {
    	    for(j = 5; j >= 0; --j) {
    	        for(i = N; i > 0; --i) {
    		    t = i + (j * N);
    		    p = out + i * 8;
    
    		    memcpy(block, out, 8);
    		    memcpy(block + 8, p, 8);
    		    block[7] ^= t;
    		
                    xmlSecNssAesOp(aeskey, block, block, enc);
    		    memcpy(out, block, 8);
    		    memcpy(p, block + 8, 8);
    	        }
    	    }
        }
        /* do not left data in memory */
        memset(block, 0, sizeof(block));
        
        if(memcmp(xmlSecNssKWAesMagicBlock, out, XMLSEC_NSS_KW_AES_MAGIC_BLOCK_SIZE) != 0) {
    	    xmlSecErr_a_ignorar5(XMLSEC_ERRORS_HERE, 
    		        NULL,
    		        NULL,
    		        XMLSEC_ERRORS_R_INVALID_DATA,
    		        "bad magic block");
    	    goto done;
        }
    	
        memmove(out, out + XMLSEC_NSS_KW_AES_MAGIC_BLOCK_SIZE, inSize - XMLSEC_NSS_KW_AES_MAGIC_BLOCK_SIZE);
        result = (inSize - XMLSEC_NSS_KW_AES_MAGIC_BLOCK_SIZE);
    }

done:
    if (aeskey != NULL) {
	PK11_FreeSymKey(aeskey);
    }

    return (result);
}
Example #27
0
/*
** Called from ssl3_HandleClientKeyExchange()
*/
SECStatus
ssl3_HandleECDHClientKeyExchange(sslSocket *ss, SSL3Opaque *b,
                                 PRUint32 length,
                                 sslKeyPair *serverKeyPair)
{
    PK11SymKey *pms;
    SECStatus rv;
    SECKEYPublicKey clntPubKey;
    CK_MECHANISM_TYPE target;
    PRBool isTLS, isTLS12;
    int errCode = SSL_ERROR_RX_MALFORMED_CLIENT_KEY_EXCH;

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

    clntPubKey.keyType = ecKey;
    clntPubKey.u.ec.DEREncodedParams.len =
        serverKeyPair->pubKey->u.ec.DEREncodedParams.len;
    clntPubKey.u.ec.DEREncodedParams.data =
        serverKeyPair->pubKey->u.ec.DEREncodedParams.data;

    rv = ssl3_ConsumeHandshakeVariable(ss, &clntPubKey.u.ec.publicValue,
                                       1, &b, &length);
    if (rv != SECSuccess) {
        PORT_SetError(errCode);
        return SECFailure;
    }

    /* we have to catch the case when the client's public key has length 0. */
    if (!clntPubKey.u.ec.publicValue.len) {
        (void)SSL3_SendAlert(ss, alert_fatal, illegal_parameter);
        PORT_SetError(errCode);
        return SECFailure;
    }

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

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

    /*  Determine the PMS */
    pms = PK11_PubDeriveWithKDF(serverKeyPair->privKey, &clntPubKey,
                                PR_FALSE, NULL, NULL,
                                CKM_ECDH1_DERIVE, target, CKA_DERIVE, 0,
                                CKD_NULL, NULL, NULL);

    if (pms == NULL) {
        /* last gasp.  */
        errCode = ssl_MapLowLevelError(SSL_ERROR_CLIENT_KEY_EXCHANGE_FAILURE);
        PORT_SetError(errCode);
        return SECFailure;
    }

    rv = ssl3_InitPendingCipherSpec(ss, pms);
    PK11_FreeSymKey(pms);
    if (rv != SECSuccess) {
        /* error code set by ssl3_InitPendingCipherSpec */
        return SECFailure;
    }
    return SECSuccess;
}
Example #28
0
static int  	
xmlSecNssKWAesOp(const xmlSecByte *key, xmlSecSize keySize,
		 const xmlSecByte *in, xmlSecSize inSize,
		 xmlSecByte *out, xmlSecSize outSize, int enc) {

    CK_MECHANISM_TYPE  cipherMech;
    PK11SlotInfo*      slot = NULL;
    PK11SymKey*        aeskey = NULL;
    SECItem*           SecParam = NULL;
    PK11Context*       EncContext = NULL;
    SECItem            keyItem;
    SECStatus          rv;
    int                result_len = -1;
    int                tmp1_outlen;
    unsigned int       tmp2_outlen;
    
    xmlSecAssert2(key != NULL, -1);
    xmlSecAssert2(keySize > 0, -1);
    xmlSecAssert2(in != NULL, -1);
    xmlSecAssert2(inSize > 0, -1);
    xmlSecAssert2(out != NULL, -1);
    xmlSecAssert2(outSize >= inSize + 8, -1);

    cipherMech = CKM_NETSCAPE_AES_KEY_WRAP;
    slot = PK11_GetBestSlot(cipherMech, NULL);
    if (slot == NULL) {
	xmlSecErr_a_ignorar5(XMLSEC_ERRORS_HERE,
		    NULL,
		    "PK11_GetBestSlot",
		    XMLSEC_ERRORS_R_CRYPTO_FAILED,
		    XMLSEC_ERRORS_NO_MESSAGE);
	goto done;
    }

    keyItem.data = (unsigned char *)key;
    keyItem.len = keySize;
    aeskey = PK11_ImportSymKey(slot, cipherMech, PK11_OriginUnwrap, 
		    	       enc ? CKA_ENCRYPT : CKA_DECRYPT, &keyItem, NULL);
    if (aeskey == NULL) {
	xmlSecErr_a_ignorar5(XMLSEC_ERRORS_HERE,
		    NULL,
		    "PK11_ImportSymKey",
		    XMLSEC_ERRORS_R_CRYPTO_FAILED,
		    XMLSEC_ERRORS_NO_MESSAGE);
	goto done;
    }

    SecParam = PK11_ParamFromIV(cipherMech, NULL);
    if (SecParam == NULL) {
	xmlSecErr_a_ignorar5(XMLSEC_ERRORS_HERE,
		    NULL,
		    "PK11_ParamFromIV",
		    XMLSEC_ERRORS_R_CRYPTO_FAILED,
		    XMLSEC_ERRORS_NO_MESSAGE);
	goto done;
    }

    EncContext = PK11_CreateContextBySymKey(cipherMech, 
		    			    enc ? CKA_ENCRYPT : CKA_DECRYPT, 
					    aeskey, SecParam);
    if (EncContext == NULL) {
	xmlSecErr_a_ignorar5(XMLSEC_ERRORS_HERE,
		    NULL,
		    "PK11_CreateContextBySymKey",
		    XMLSEC_ERRORS_R_CRYPTO_FAILED,
		    XMLSEC_ERRORS_NO_MESSAGE);
	goto done;
    }

    tmp1_outlen = tmp2_outlen = 0;
    rv = PK11_CipherOp(EncContext, out, &tmp1_outlen, outSize,
		       (unsigned char *)in, inSize);
    if (rv != SECSuccess) {
	xmlSecErr_a_ignorar5(XMLSEC_ERRORS_HERE,
		    NULL,
		    "PK11_CipherOp",
		    XMLSEC_ERRORS_R_CRYPTO_FAILED,
		    XMLSEC_ERRORS_NO_MESSAGE);
	goto done;
    }

    rv = PK11_DigestFinal(EncContext, out+tmp1_outlen, 
		    	  &tmp2_outlen, outSize-tmp1_outlen);
    if (rv != SECSuccess) {
	xmlSecErr_a_ignorar5(XMLSEC_ERRORS_HERE,
		    NULL,
		    "PK11_DigestFinal",
		    XMLSEC_ERRORS_R_CRYPTO_FAILED,
		    XMLSEC_ERRORS_NO_MESSAGE);
	goto done;
    }

    result_len = tmp1_outlen + tmp2_outlen;

done:
    if (slot) {
	PK11_FreeSlot(slot);
    }
    if (aeskey) {
	PK11_FreeSymKey(aeskey);
    }
    if (SecParam) {
	SECITEM_FreeItem(SecParam, PR_TRUE);
    }
    if (EncContext) {
	PK11_DestroyContext(EncContext, PR_TRUE);
    }

    return(result_len);
}
Example #29
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;
}
Example #30
0
void genkey(int id)
{
  PK11SlotInfo*  slot = NULL;
  PK11SymKey*    key = NULL;
  SECItem        keyiditem;
  int            keyid[1];
  CK_MECHANISM_TYPE cipherMech;
 
  /* using CKM_AES_CBC_PAD mechanism for example */
  cipherMech = CKM_AES_CBC_PAD;
 
   slot = PK11_GetInternalKeySlot();
  /* slot = PK11_GetBestSlot(cipherMech, NULL); didn't work.
   * Error code: token is read-only. ??
   */
  if (slot == NULL)
  {
    fprintf(stderr, "Unable to find security device (err %d)\n",
            PR_GetError());
    return;
  }

  keyid[0] = id;
  keyiditem.type = siBuffer;
  keyiditem.data = (void *)keyid;
  keyiditem.len = sizeof(keyid[0]);

  /* Note: keysize must be 0 for fixed key-length algorithms like DES.
   *       Since we're using AES in this example, we're specifying
   *       one of the valid keysizes (16, 24, 32)
   */
  key = PK11_TokenKeyGen(slot, cipherMech, 0, 32 /*keysize*/,
                         &keyiditem, PR_TRUE, 0);
  if (key == NULL)
  {
    fprintf(stderr, "PK11_TokenKeyGen failed (err %d)\n",
            PR_GetError());
    PK11_FreeSlot(slot);
    return;
  }

  fprintf(stderr, "key length of generated key is %d\n",
          PK11_GetKeyLength(key));
  fprintf(stderr, "mechanism of key is %d (asked for %d)\n",
          PK11_GetMechanism(key), cipherMech);

  PK11_FreeSymKey(key);


  key = PK11_FindFixedKey(slot, cipherMech, &keyiditem, 0);
  if (key == NULL)
  {
    fprintf(stderr, "PK11_FindFixedKey failed (err %d)\n",
            PR_GetError());
    PK11_FreeSlot(slot);
    return;
  }

  fprintf(stderr, "Found key!\n");
  fprintf(stderr, "key length of generated key is %d\n",
          PK11_GetKeyLength(key));
  fprintf(stderr, "mechanism of key is %d (asked for %d)\n",
          PK11_GetMechanism(key), cipherMech);

  PK11_FreeSymKey(key);

  PK11_FreeSlot(slot);
}