Exemplo n.º 1
0
static PK11Context*
sipe_crypt_ctx_create(CK_MECHANISM_TYPE cipherMech, const guchar *key, gsize key_length)
{
	PK11SlotInfo* slot;
	SECItem keyItem;
	SECItem ivItem;
	PK11SymKey* SymKey;
	SECItem *SecParam;
	PK11Context* EncContext;

	/* For key */
	slot = PK11_GetBestSlot(cipherMech, NULL);

	keyItem.type = siBuffer;
	keyItem.data = (unsigned char *)key;
	keyItem.len = key_length;

	SymKey = PK11_ImportSymKey(slot, cipherMech, PK11_OriginUnwrap, CKA_ENCRYPT, &keyItem, NULL);

	/* Parameter for crypto context */
	ivItem.type = siBuffer;
	ivItem.data = NULL;
	ivItem.len = 0;
	SecParam = PK11_ParamFromIV(cipherMech, &ivItem);
	
	EncContext = PK11_CreateContextBySymKey(cipherMech, CKA_ENCRYPT, SymKey, SecParam);

	PK11_FreeSymKey(SymKey);
	SECITEM_FreeItem(SecParam, PR_TRUE);
	PK11_FreeSlot(slot);

	return EncContext;
}
Exemplo n.º 2
0
CryptoRc4
crypto_rc4_init(uint8 * key, uint32 len)
{
	CryptoRc4 rc4 = xmalloc(sizeof(*rc4));
	CK_MECHANISM_TYPE cipherMech = CKM_RC4;

	PK11SlotInfo* slot = PK11_GetInternalKeySlot();
	ASSERT(slot);

	SECItem keyItem;
	keyItem.type = siBuffer;
	keyItem.data = key;
	keyItem.len = len;

	PK11SymKey* symKey = PK11_ImportSymKey(slot, cipherMech, PK11_OriginUnwrap, CKA_ENCRYPT, &keyItem, NULL);
	ASSERT(symKey);

	SECItem* secParam = PK11_ParamFromIV(cipherMech, NULL);
	ASSERT(secParam);

	rc4->context = PK11_CreateContextBySymKey(cipherMech, CKA_ENCRYPT, symKey, secParam);
	ASSERT(rc4->context);

	PK11_FreeSymKey(symKey);
	SECITEM_FreeItem(secParam, PR_TRUE);
	PK11_FreeSlot(slot);

	return rc4;
}
Exemplo n.º 3
0
/**
 * @brief Initialise a context for decrypting arbitrary data using the given key.
 * @note If *ctx is NULL, a apr_crypto_block_t will be created from a pool. If
 *       *ctx is not NULL, *ctx must point at a previously created structure.
 * @param ctx The block context returned, see note.
 * @param blockSize The block size of the cipher.
 * @param iv Optional initialisation vector. If the buffer pointed to is NULL,
 *           an IV will be created at random, in space allocated from the pool.
 *           If the buffer is not NULL, the IV in the buffer will be used.
 * @param key The key structure.
 * @param p The pool to use.
 * @return Returns APR_ENOIV if an initialisation vector is required but not specified.
 *         Returns APR_EINIT if the backend failed to initialise the context. Returns
 *         APR_ENOTIMPL if not implemented.
 */
static apr_status_t crypto_block_decrypt_init(apr_crypto_block_t **ctx,
        apr_size_t *blockSize, const unsigned char *iv,
        const apr_crypto_key_t *key, apr_pool_t *p)
{
    PRErrorCode perr;
    SECItem * secParam;
    apr_crypto_block_t *block = *ctx;
    if (!block) {
        *ctx = block = apr_pcalloc(p, sizeof(apr_crypto_block_t));
    }
    if (!block) {
        return APR_ENOMEM;
    }
    block->f = key->f;
    block->pool = p;
    block->provider = key->provider;

    apr_pool_cleanup_register(p, block, crypto_block_cleanup_helper,
            apr_pool_cleanup_null);

    if (key->ivSize) {
        SECItem ivItem;
        if (iv == NULL) {
            return APR_ENOIV; /* Cannot initialise without an IV */
        }
        ivItem.data = (unsigned char*) iv;
        ivItem.len = key->ivSize;
        secParam = PK11_ParamFromIV(key->cipherMech, &ivItem);
    }
    else {
        secParam = PK11_GenerateNewParam(key->cipherMech, key->symKey);
    }
    block->blockSize = PK11_GetBlockSize(key->cipherMech, secParam);
    block->ctx = PK11_CreateContextBySymKey(key->cipherMech, CKA_DECRYPT,
            key->symKey, secParam);

    /* did an error occur? */
    perr = PORT_GetError();
    if (perr || !block->ctx) {
        key->f->result->rc = perr;
        key->f->result->msg = PR_ErrorToName(perr);
        return APR_EINIT;
    }

    if (blockSize) {
        *blockSize = PK11_GetBlockSize(key->cipherMech, secParam);
    }

    return APR_SUCCESS;

}
Exemplo n.º 4
0
nsresult
nsStreamCipher::InitWithIV_(nsIKeyObject *aKey, SECItem* aIV)
{
  NS_ENSURE_ARG_POINTER(aKey);

  // Make sure we have a SYM_KEY.
  PRInt16 keyType;
  nsresult rv = aKey->GetType(&keyType);
  NS_ENSURE_SUCCESS(rv, rv);
  if (keyType != nsIKeyObject::SYM_KEY)
    return NS_ERROR_INVALID_ARG;

  if (mContext)
    PK11_DestroyContext(mContext, true /* free sub-objects */);

  // Get the PK11SymKey out of the key object and create the PK11Context.
  void* keyObj;
  rv = aKey->GetKeyObj(&keyObj);
  NS_ENSURE_SUCCESS(rv, rv);

  PK11SymKey *symkey = reinterpret_cast<PK11SymKey*>(keyObj);
  if (!symkey)
    return NS_ERROR_FAILURE;

  CK_MECHANISM_TYPE cipherMech = PK11_GetMechanism(symkey);

  SECItem *param = nullptr;
  // aIV may be null
  param = PK11_ParamFromIV(cipherMech, aIV);
  if (!param)
    return NS_ERROR_FAILURE;

  mContext = PK11_CreateContextBySymKey(cipherMech, CKA_ENCRYPT,
                                        symkey, param);

  SECITEM_FreeItem(param, true);

  // Something went wrong if mContext doesn't exist.
  if (!mContext)
    return NS_ERROR_FAILURE;

  // Everything went ok.      
  mValue.Truncate();
  return NS_OK;
}
Exemplo n.º 5
0
static int nss_encrypt_decrypt_init(struct crypto_mech_data *mech_props,
                                    bool do_encrypt,
                                    struct sss_nss_crypto_ctx *cctx)
{
    CK_ATTRIBUTE_TYPE   op;
    int ret;

    op = do_encrypt ? CKA_ENCRYPT : CKA_DECRYPT;

    /* turn the raw key into a key object */
    cctx->keyobj = PK11_ImportSymKey(cctx->slot, mech_props->cipher,
                                     PK11_OriginUnwrap, op, cctx->key, NULL);
    if (cctx->keyobj == NULL) {
        DEBUG(SSSDBG_CRIT_FAILURE, "Failure to import key into NSS (err %d)\n",
                  PR_GetError());
        ret = EIO;
        goto done;
    }

    /* turn the raw IV into a initialization vector object */
    cctx->sparam = PK11_ParamFromIV(mech_props->cipher, cctx->iv);
    if (cctx->sparam == NULL) {
        DEBUG(SSSDBG_CRIT_FAILURE, "Failure to set up PKCS11 param (err %d)\n",
                  PR_GetError());
        ret = EIO;
        goto done;
    }

    /* Create cipher context */
    cctx->ectx = PK11_CreateContextBySymKey(mech_props->cipher, op,
                                            cctx->keyobj, cctx->sparam);
    if (cctx->ectx == NULL) {
        DEBUG(SSSDBG_CRIT_FAILURE, "Cannot create cipher context (err %d)\n",
                  PORT_GetError());
        ret = EIO;
        goto done;
    }

    ret = EOK;
done:
    return ret;
}
Exemplo n.º 6
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;
}
// Convert an opaque key handle aKeyHandle back into a Private Key object, using
// the long-lived aPersistentKey mixed with aAppParam and the AES Key Wrap
// algorithm.
static UniqueSECKEYPrivateKey
PrivateKeyFromKeyHandle(const UniquePK11SlotInfo& aSlot,
                        const UniquePK11SymKey& aPersistentKey,
                        uint8_t* aKeyHandle, uint32_t aKeyHandleLen,
                        uint8_t* aAppParam, uint32_t aAppParamLen,
                        const nsNSSShutDownPreventionLock&)
{
  MOZ_ASSERT(aSlot);
  MOZ_ASSERT(aPersistentKey);
  MOZ_ASSERT(aKeyHandle);
  MOZ_ASSERT(aAppParam);
  MOZ_ASSERT(aAppParamLen == SHA256_LENGTH);
  if (NS_WARN_IF(!aSlot || !aPersistentKey || !aKeyHandle || !aAppParam ||
                 aAppParamLen != SHA256_LENGTH)) {
    return nullptr;
  }

  // As we only support one key format ourselves (right now), fail early if
  // we aren't that length
  if (NS_WARN_IF(aKeyHandleLen != kVersion1KeyHandleLen)) {
    return nullptr;
  }

  if (NS_WARN_IF(aKeyHandle[0] != SoftTokenHandle::Version1)) {
    // Unrecognized version
    return nullptr;
  }

  uint8_t saltLen = aKeyHandle[1];
  uint8_t* saltPtr = aKeyHandle + 2;
  if (NS_WARN_IF(saltLen != kSaltByteLen)) {
    return nullptr;
  }

  // Prepare the HKDF (https://tools.ietf.org/html/rfc5869)
  CK_NSS_HKDFParams hkdfParams = { true, saltPtr, saltLen,
                                   true, aAppParam, aAppParamLen };
  SECItem kdfParams = { siBuffer, (unsigned char*)&hkdfParams,
                        sizeof(hkdfParams) };

  // Derive a wrapping key from aPersistentKey, the salt, and the aAppParam.
  // CKM_AES_KEY_GEN and CKA_WRAP are key type and usage attributes of the
  // derived symmetric key and don't matter because we ignore them anyway.
  UniquePK11SymKey wrapKey(PK11_Derive(aPersistentKey.get(), CKM_NSS_HKDF_SHA256,
                                       &kdfParams, CKM_AES_KEY_GEN, CKA_WRAP,
                                       kWrappingKeyByteLen));
  if (NS_WARN_IF(!wrapKey.get())) {
    MOZ_LOG(gNSSTokenLog, LogLevel::Warning,
            ("Failed to derive a wrapping key, NSS error #%d", PORT_GetError()));
    return nullptr;
  }

  uint8_t wrappedLen = aKeyHandleLen - saltLen - 2;
  uint8_t* wrappedPtr = aKeyHandle + saltLen + 2;

  ScopedAutoSECItem wrappedKeyItem(wrappedLen);
  memcpy(wrappedKeyItem.data, wrappedPtr, wrappedKeyItem.len);

  ScopedAutoSECItem pubKey(kPublicKeyLen);

  UniqueSECItem param(PK11_ParamFromIV(CKM_NSS_AES_KEY_WRAP_PAD,
                                       /* default IV */ nullptr ));

  CK_ATTRIBUTE_TYPE usages[] = { CKA_SIGN };
  int usageCount = 1;

  UniqueSECKEYPrivateKey unwrappedKey(
    PK11_UnwrapPrivKey(aSlot.get(), wrapKey.get(), CKM_NSS_AES_KEY_WRAP_PAD,
                       param.get(), &wrappedKeyItem,
                       /* no nickname */ nullptr,
                       /* discard pubkey */ &pubKey,
                       /* not permanent */ false,
                       /* non-exportable */ true,
                       CKK_EC, usages, usageCount,
                       /* wincx */ nullptr));
  if (NS_WARN_IF(!unwrappedKey)) {
    // Not our key.
    MOZ_LOG(gNSSTokenLog, LogLevel::Debug,
            ("Could not unwrap key handle, NSS Error #%d", PORT_GetError()));
    return nullptr;
  }

  return unwrappedKey;
}
// Convert a Private Key object into an opaque key handle, using AES Key Wrap
// with the long-lived aPersistentKey mixed with aAppParam to convert aPrivKey.
// The key handle's format is version || saltLen || salt || wrappedPrivateKey
static UniqueSECItem
KeyHandleFromPrivateKey(const UniquePK11SlotInfo& aSlot,
                        const UniquePK11SymKey& aPersistentKey,
                        uint8_t* aAppParam, uint32_t aAppParamLen,
                        const UniqueSECKEYPrivateKey& aPrivKey,
                        const nsNSSShutDownPreventionLock&)
{
  MOZ_ASSERT(aSlot);
  MOZ_ASSERT(aPersistentKey);
  MOZ_ASSERT(aAppParam);
  MOZ_ASSERT(aPrivKey);
  if (NS_WARN_IF(!aSlot || !aPersistentKey || !aPrivKey || !aAppParam)) {
    return nullptr;
  }

  // Generate a random salt
  uint8_t saltParam[kSaltByteLen];
  SECStatus srv = PK11_GenerateRandomOnSlot(aSlot.get(), saltParam,
                                            sizeof(saltParam));
  if (NS_WARN_IF(srv != SECSuccess)) {
    MOZ_LOG(gNSSTokenLog, LogLevel::Warning,
            ("Failed to generate a salt, NSS error #%d", PORT_GetError()));
    return nullptr;
  }

  // Prepare the HKDF (https://tools.ietf.org/html/rfc5869)
  CK_NSS_HKDFParams hkdfParams = { true, saltParam, sizeof(saltParam),
                                   true, aAppParam, aAppParamLen };
  SECItem kdfParams = { siBuffer, (unsigned char*)&hkdfParams,
                        sizeof(hkdfParams) };

  // Derive a wrapping key from aPersistentKey, the salt, and the aAppParam.
  // CKM_AES_KEY_GEN and CKA_WRAP are key type and usage attributes of the
  // derived symmetric key and don't matter because we ignore them anyway.
  UniquePK11SymKey wrapKey(PK11_Derive(aPersistentKey.get(), CKM_NSS_HKDF_SHA256,
                                       &kdfParams, CKM_AES_KEY_GEN, CKA_WRAP,
                                       kWrappingKeyByteLen));
  if (NS_WARN_IF(!wrapKey.get())) {
    MOZ_LOG(gNSSTokenLog, LogLevel::Warning,
            ("Failed to derive a wrapping key, NSS error #%d", PORT_GetError()));
    return nullptr;
  }

  UniqueSECItem wrappedKey(::SECITEM_AllocItem(/* default arena */ nullptr,
                                               /* no buffer */ nullptr,
                                               kWrappedKeyBufLen));
  if (NS_WARN_IF(!wrappedKey)) {
    MOZ_LOG(gNSSTokenLog, LogLevel::Warning, ("Failed to allocate memory"));
    return nullptr;
  }

  UniqueSECItem param(PK11_ParamFromIV(CKM_NSS_AES_KEY_WRAP_PAD,
                                       /* default IV */ nullptr ));

  srv = PK11_WrapPrivKey(aSlot.get(), wrapKey.get(), aPrivKey.get(),
                         CKM_NSS_AES_KEY_WRAP_PAD, param.get(), wrappedKey.get(),
                         /* wincx */ nullptr);
  if (NS_WARN_IF(srv != SECSuccess)) {
    MOZ_LOG(gNSSTokenLog, LogLevel::Warning,
            ("Failed to wrap U2F key, NSS error #%d", PORT_GetError()));
    return nullptr;
  }

  // Concatenate the salt and the wrapped Private Key together
  mozilla::dom::CryptoBuffer keyHandleBuf;
  if (NS_WARN_IF(!keyHandleBuf.SetCapacity(wrappedKey.get()->len + sizeof(saltParam) + 2,
                                           mozilla::fallible))) {
    MOZ_LOG(gNSSTokenLog, LogLevel::Warning, ("Failed to allocate memory"));
    return nullptr;
  }

  // It's OK to ignore the return values here because we're writing into
  // pre-allocated space
  keyHandleBuf.AppendElement(SoftTokenHandle::Version1, mozilla::fallible);
  keyHandleBuf.AppendElement(sizeof(saltParam), mozilla::fallible);
  keyHandleBuf.AppendElements(saltParam, sizeof(saltParam), mozilla::fallible);
  keyHandleBuf.AppendSECItem(wrappedKey.get());

  UniqueSECItem keyHandle(::SECITEM_AllocItem(nullptr, nullptr, 0));
  if (NS_WARN_IF(!keyHandle)) {
    MOZ_LOG(gNSSTokenLog, LogLevel::Warning, ("Failed to allocate memory"));
    return nullptr;
  }

  if (NS_WARN_IF(!keyHandleBuf.ToSECItem(/* default arena */ nullptr, keyHandle.get()))) {
    MOZ_LOG(gNSSTokenLog, LogLevel::Warning, ("Failed to allocate memory"));
    return nullptr;
  }
  return keyHandle;
}
Exemplo n.º 9
0
size_t ssl_des3_encrypt(const unsigned char *key, size_t key_len,
			const unsigned char *input, size_t input_len,
			const unsigned char *iv, unsigned char **res)
{
#define CIPHER_MECH CKM_DES3_CBC
#define MAX_OUTPUT_LEN 72

	int len1;
	unsigned int len2;

	PK11Context *ctx = NULL;
	PK11SlotInfo *slot = NULL;
	SECItem keyItem;
	SECItem ivItem;
	SECItem *secParam = NULL;
	PK11SymKey *symKey = NULL;

	size_t rc;
	SECStatus rv;

	if (!initialized) {
		ssl_init();
	}

	keyItem.data = (unsigned char *)key;
	keyItem.len = key_len;

	slot = PK11_GetBestSlot(CIPHER_MECH, NULL);
	if (slot == NULL) {
		fprintf(stderr, "PK11_GetBestSlot failed (err %d)\n",
			PR_GetError());
		rc = 0;
		goto out;
	}

	symKey =
	    PK11_ImportSymKey(slot, CIPHER_MECH, PK11_OriginUnwrap, CKA_ENCRYPT,
			      &keyItem, NULL);
	if (symKey == NULL) {
		fprintf(stderr, "PK11_ImportSymKey failed (err %d)\n",
			PR_GetError());
		rc = 0;
		goto out;
	}

	ivItem.data = (unsigned char *)iv;
	/* See msn_soap_passport_sso_handle_response in protocols/msn/soap.c */
	ivItem.len = 8;

	secParam = PK11_ParamFromIV(CIPHER_MECH, &ivItem);
	if (secParam == NULL) {
		fprintf(stderr, "PK11_ParamFromIV failed (err %d)\n",
			PR_GetError());
		rc = 0;
		goto out;
	}

	ctx =
	    PK11_CreateContextBySymKey(CIPHER_MECH, CKA_ENCRYPT, symKey,
				       secParam);
	if (ctx == NULL) {
		fprintf(stderr, "PK11_CreateContextBySymKey failed (err %d)\n",
			PR_GetError());
		rc = 0;
		goto out;
	}

	*res = g_new0(unsigned char, MAX_OUTPUT_LEN);

	rv = PK11_CipherOp(ctx, *res, &len1, MAX_OUTPUT_LEN,
			   (unsigned char *)input, input_len);
	if (rv != SECSuccess) {
		fprintf(stderr, "PK11_CipherOp failed (err %d)\n",
			PR_GetError());
		rc = 0;
		goto out;
	}

	assert(len1 <= MAX_OUTPUT_LEN);

	rv = PK11_DigestFinal(ctx, *res + len1, &len2,
			      (unsigned int)MAX_OUTPUT_LEN - len1);
	if (rv != SECSuccess) {
		fprintf(stderr, "PK11_DigestFinal failed (err %d)\n",
			PR_GetError());
		rc = 0;
		goto out;
	}

	rc = len1 + len2;

 out:
	if (ctx)
		PK11_DestroyContext(ctx, PR_TRUE);
	if (symKey)
		PK11_FreeSymKey(symKey);
	if (secParam)
		SECITEM_FreeItem(secParam, PR_TRUE);
	if (slot)
		PK11_FreeSlot(slot);

	return rc;
}
/*
 * create a new parameter block from the passed in MECHANISM and the
 * key. Use Netscape's S/MIME Rules for the New param block.
 */
SECItem *
pk11_GenerateNewParamWithKeyLen(CK_MECHANISM_TYPE type, int keyLen) 
{ 
    CK_RC2_CBC_PARAMS *rc2_params;
    CK_RC2_PARAMS *rc2_ecb_params;
    SECItem *mech;
    SECItem iv;
    SECStatus rv;


    mech = (SECItem *) PORT_Alloc(sizeof(SECItem));
    if (mech == NULL) return NULL;

    rv = SECSuccess;
    mech->type = siBuffer;
    switch (type) {
    case CKM_RC4:
    case CKM_SEED_ECB:
    case CKM_CAMELLIA_ECB:
    case CKM_AES_ECB:
    case CKM_DES_ECB:
    case CKM_DES3_ECB:
    case CKM_IDEA_ECB:
    case CKM_CDMF_ECB:
    case CKM_CAST_ECB:
    case CKM_CAST3_ECB:
    case CKM_CAST5_ECB:
	mech->data = NULL;
	mech->len = 0;
	break;
    case CKM_RC2_ECB:
	rc2_ecb_params = (CK_RC2_PARAMS *)PORT_Alloc(sizeof(CK_RC2_PARAMS));
	if (rc2_ecb_params == NULL) {
	    rv = SECFailure;
	    break;
	}
	/* NOTE PK11_GetKeyLength can return -1 if the key isn't and RC2, RC5,
	 *   or RC4 key. Of course that wouldn't happen here doing RC2:).*/
	*rc2_ecb_params = keyLen ? keyLen*8 : 128;
	mech->data = (unsigned char *) rc2_ecb_params;
	mech->len = sizeof(CK_RC2_PARAMS);
	break;
    case CKM_RC2_CBC:
    case CKM_RC2_CBC_PAD:
	rv = pk11_GenIV(type,&iv);
	if (rv != SECSuccess) {
	    break;
	}
	rc2_params = (CK_RC2_CBC_PARAMS *)PORT_Alloc(sizeof(CK_RC2_CBC_PARAMS));
	if (rc2_params == NULL) {
	    PORT_Free(iv.data);
	    rv = SECFailure;
	    break;
	}
	/* NOTE PK11_GetKeyLength can return -1 if the key isn't and RC2, RC5,
	 *   or RC4 key. Of course that wouldn't happen here doing RC2:).*/
	rc2_params->ulEffectiveBits = keyLen ? keyLen*8 : 128;
	if (iv.data)
	    PORT_Memcpy(rc2_params->iv,iv.data,sizeof(rc2_params->iv));
	mech->data = (unsigned char *) rc2_params;
	mech->len = sizeof(CK_RC2_CBC_PARAMS);
	PORT_Free(iv.data);
	break;
    case CKM_RC5_ECB:
        PORT_Free(mech);
	return PK11_ParamFromIV(type,NULL);
    case CKM_RC5_CBC:
    case CKM_RC5_CBC_PAD:
	rv = pk11_GenIV(type,&iv);
	if (rv != SECSuccess) {
	    break;
	}
        PORT_Free(mech);
	return PK11_ParamFromIV(type,&iv);
    default:
	if (pk11_lookup(type)->iv == 0) {
	    mech->data = NULL;
	    mech->len = 0;
	    break;
	}
    case CKM_SEED_CBC:
    case CKM_CAMELLIA_CBC:
    case CKM_AES_CBC:
    case CKM_DES_CBC:
    case CKM_DES3_CBC:
    case CKM_IDEA_CBC:
    case CKM_CDMF_CBC:
    case CKM_CAST_CBC:
    case CKM_CAST3_CBC:
    case CKM_CAST5_CBC:
    case CKM_DES_CBC_PAD:
    case CKM_DES3_CBC_PAD:
    case CKM_IDEA_CBC_PAD:
    case CKM_CDMF_CBC_PAD:
    case CKM_CAST_CBC_PAD:
    case CKM_CAST3_CBC_PAD:
    case CKM_CAST5_CBC_PAD:
    case CKM_SKIPJACK_CBC64:
    case CKM_SKIPJACK_ECB64:
    case CKM_SKIPJACK_OFB64:
    case CKM_SKIPJACK_CFB64:
    case CKM_SKIPJACK_CFB32:
    case CKM_SKIPJACK_CFB16:
    case CKM_SKIPJACK_CFB8:
    case CKM_BATON_ECB128:
    case CKM_BATON_ECB96:
    case CKM_BATON_CBC128:
    case CKM_BATON_COUNTER:
    case CKM_BATON_SHUFFLE:
    case CKM_JUNIPER_ECB128:
    case CKM_JUNIPER_CBC128:
    case CKM_JUNIPER_COUNTER:
    case CKM_JUNIPER_SHUFFLE:
	rv = pk11_GenIV(type,&iv);
	if (rv != SECSuccess) {
	    break;
	}
	mech->data = (unsigned char*)PORT_Alloc(iv.len);
	if (mech->data == NULL) {
	    PORT_Free(iv.data);
	    rv = SECFailure;
	    break;
	}
	PORT_Memcpy(mech->data,iv.data,iv.len);
	mech->len = iv.len;
        PORT_Free(iv.data);
	break;
    }
    if (rv !=  SECSuccess) {
	SECITEM_FreeItem(mech,PR_TRUE);
	return NULL;
    }
    return mech;

}
Exemplo n.º 11
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);
}
Exemplo n.º 12
0
/**
 * @brief Initialise a context for encrypting arbitrary data using the given key.
 * @note If *ctx is NULL, a apr_crypto_block_t will be created from a pool. If
 *       *ctx is not NULL, *ctx must point at a previously created structure.
 * @param ctx The block context returned, see note.
 * @param iv Optional initialisation vector. If the buffer pointed to is NULL,
 *           an IV will be created at random, in space allocated from the pool.
 *           If the buffer pointed to is not NULL, the IV in the buffer will be
 *           used.
 * @param key The key structure.
 * @param blockSize The block size of the cipher.
 * @param p The pool to use.
 * @return Returns APR_ENOIV if an initialisation vector is required but not specified.
 *         Returns APR_EINIT if the backend failed to initialise the context. Returns
 *         APR_ENOTIMPL if not implemented.
 */
static apr_status_t crypto_block_encrypt_init(apr_crypto_block_t **ctx,
        const unsigned char **iv, const apr_crypto_key_t *key,
        apr_size_t *blockSize, apr_pool_t *p)
{
    PRErrorCode perr;
    SECItem * secParam;
    SECItem ivItem;
    unsigned char * usedIv;
    apr_crypto_block_t *block = *ctx;
    if (!block) {
        *ctx = block = apr_pcalloc(p, sizeof(apr_crypto_block_t));
    }
    if (!block) {
        return APR_ENOMEM;
    }
    block->f = key->f;
    block->pool = p;
    block->provider = key->provider;

    apr_pool_cleanup_register(p, block, crypto_block_cleanup_helper,
            apr_pool_cleanup_null);

    if (key->ivSize) {
        if (iv == NULL) {
            return APR_ENOIV;
        }
        if (*iv == NULL) {
            SECStatus s;
            usedIv = apr_pcalloc(p, key->ivSize);
            if (!usedIv) {
                return APR_ENOMEM;
            }
            apr_crypto_clear(p, usedIv, key->ivSize);
            s = PK11_GenerateRandom(usedIv, key->ivSize);
            if (s != SECSuccess) {
                return APR_ENOIV;
            }
            *iv = usedIv;
        }
        else {
            usedIv = (unsigned char *) *iv;
        }
        ivItem.data = usedIv;
        ivItem.len = key->ivSize;
        secParam = PK11_ParamFromIV(key->cipherMech, &ivItem);
    }
    else {
        secParam = PK11_GenerateNewParam(key->cipherMech, key->symKey);
    }
    block->blockSize = PK11_GetBlockSize(key->cipherMech, secParam);
    block->ctx = PK11_CreateContextBySymKey(key->cipherMech, CKA_ENCRYPT,
            key->symKey, secParam);

    /* did an error occur? */
    perr = PORT_GetError();
    if (perr || !block->ctx) {
        key->f->result->rc = perr;
        key->f->result->msg = PR_ErrorToName(perr);
        return APR_EINIT;
    }

    if (blockSize) {
        *blockSize = PK11_GetBlockSize(key->cipherMech, secParam);
    }

    return APR_SUCCESS;

}
Exemplo n.º 13
0
void do_3des_nss(u_int8_t *buf, size_t buf_len,
		PK11SymKey *symkey, u_int8_t *iv, bool enc)
{
	u_int8_t *tmp_buf;
	u_int8_t *new_iv;

	CK_MECHANISM_TYPE ciphermech;
	SECItem ivitem;
	SECItem *secparam;
	PK11Context *enccontext = NULL;
	SECStatus rv;
	int outlen;

	DBG(DBG_CRYPT,
		DBG_log("NSS: do_3des init start"));

	ciphermech = CKM_DES3_CBC;	/* libreswan provides padding */

	if (symkey == NULL) {
		loglog(RC_LOG_SERIOUS,
			"do_3des: NSS derived enc key is NULL");
		abort();
	}

	ivitem.type = siBuffer;
	ivitem.data = iv;
	ivitem.len = DES_CBC_BLOCK_SIZE;

	secparam = PK11_ParamFromIV(ciphermech, &ivitem);
	if (secparam == NULL) {
		loglog(RC_LOG_SERIOUS,
			"do_3des: Failure to set up PKCS11 param (err %d)",
			PR_GetError());
		abort();
	}

	outlen = 0;
	tmp_buf = PR_Malloc((PRUint32)buf_len);
	new_iv = (u_int8_t*)PR_Malloc((PRUint32)DES_CBC_BLOCK_SIZE);

	if (!enc)
		memcpy(new_iv, (char*) buf + buf_len - DES_CBC_BLOCK_SIZE,
			DES_CBC_BLOCK_SIZE);

	enccontext = PK11_CreateContextBySymKey(ciphermech,
						enc ? CKA_ENCRYPT :
						CKA_DECRYPT, symkey,
						secparam);
	if (enccontext == NULL) {
		loglog(RC_LOG_SERIOUS,
			"do_3des: PKCS11 context creation failure (err %d)",
			PR_GetError());
		abort();
	}
	rv = PK11_CipherOp(enccontext, tmp_buf, &outlen, buf_len, buf,
			buf_len);
	if (rv != SECSuccess) {
		loglog(RC_LOG_SERIOUS,
			"do_3des: PKCS11 operation failure (err %d)",
			PR_GetError());
		abort();
	}

	if (enc)
		memcpy(new_iv, (char*) tmp_buf + buf_len - DES_CBC_BLOCK_SIZE,
			DES_CBC_BLOCK_SIZE);

	memcpy(buf, tmp_buf, buf_len);
	memcpy(iv, new_iv, DES_CBC_BLOCK_SIZE);
	PK11_DestroyContext(enccontext, PR_TRUE);
	PR_Free(tmp_buf);
	PR_Free(new_iv);

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

	DBG(DBG_CRYPT,
		DBG_log("NSS: do_3des init end"));
}
Exemplo n.º 14
0
static int encrypt_nss(
	knet_handle_t knet_h,
	const struct iovec *iov,
	int iovcnt,
	unsigned char *buf_out,
	ssize_t *buf_out_len)
{
	struct nsscrypto_instance *instance = knet_h->crypto_instance->model_instance;
	PK11Context*	crypt_context = NULL;
	SECItem		crypt_param;
	SECItem		*nss_sec_param = NULL;
	int		tmp_outlen = 0, tmp1_outlen = 0;
	unsigned int	tmp2_outlen = 0;
	unsigned char	*salt = buf_out;
	unsigned char	*data = buf_out + SALT_SIZE;
	int		err = -1;
	int		i;

	if (PK11_GenerateRandom (salt, SALT_SIZE) != SECSuccess) {
		log_err(knet_h, KNET_SUB_NSSCRYPTO, "Failure to generate a random number %d",
			   PR_GetError());
		goto out;
	}

	crypt_param.type = siBuffer;
	crypt_param.data = salt;
	crypt_param.len = SALT_SIZE;

	nss_sec_param = PK11_ParamFromIV (cipher_to_nss[instance->crypto_cipher_type],
					  &crypt_param);
	if (nss_sec_param == NULL) {
		log_err(knet_h, KNET_SUB_NSSCRYPTO, "Failure to set up PKCS11 param (err %d)",
			   PR_GetError());
		goto out;
	}

	/*
	 * Create cipher context for encryption
	 */
	crypt_context = PK11_CreateContextBySymKey (cipher_to_nss[instance->crypto_cipher_type],
						    CKA_ENCRYPT,
						    instance->nss_sym_key,
						    nss_sec_param);
	if (!crypt_context) {
		log_err(knet_h, KNET_SUB_NSSCRYPTO, "PK11_CreateContext failed (encrypt) crypt_type=%d (err %d)",
			   (int)cipher_to_nss[instance->crypto_cipher_type],
			   PR_GetError());
		goto out;
	}

	for (i=0; i<iovcnt; i++) {
		if (PK11_CipherOp(crypt_context, data,
				  &tmp_outlen,
				  KNET_DATABUFSIZE_CRYPT,
				  (unsigned char *)iov[i].iov_base, iov[i].iov_len) != SECSuccess) {
			log_err(knet_h, KNET_SUB_NSSCRYPTO, "PK11_CipherOp failed (encrypt) crypt_type=%d (err %d)",
				   (int)cipher_to_nss[instance->crypto_cipher_type],
				   PR_GetError());
			goto out;
		}
		tmp1_outlen = tmp1_outlen + tmp_outlen;
	}

	if (PK11_DigestFinal(crypt_context, data + tmp1_outlen,
			     &tmp2_outlen, KNET_DATABUFSIZE_CRYPT - tmp1_outlen) != SECSuccess) {
		log_err(knet_h, KNET_SUB_NSSCRYPTO, "PK11_DigestFinal failed (encrypt) crypt_type=%d (err %d)",
			   (int)cipher_to_nss[instance->crypto_cipher_type],
			   PR_GetError());
		goto out;

	}

	*buf_out_len = tmp1_outlen + tmp2_outlen + SALT_SIZE;

	err = 0;

out:
	if (crypt_context) {
		PK11_DestroyContext(crypt_context, PR_TRUE);
	}
	if (nss_sec_param) {
		SECITEM_FreeItem(nss_sec_param, PR_TRUE);
	}
	return err;
}
Exemplo n.º 15
0
static void
do_aes(u_int8_t *buf, size_t buf_len, u_int8_t *key, size_t key_size, u_int8_t *iv, bool enc)
{

    u_int8_t iv_bak[AES_CBC_BLOCK_SIZE];
    u_int8_t *new_iv = NULL;        /* logic will avoid copy to NULL */
    u_int8_t *tmp_buf; 

    CK_MECHANISM_TYPE  ciphermech;
    SECItem              ivitem;
    SECItem*           secparam = NULL;
    PK11SymKey*        symkey = NULL;
    PK11Context*       enccontext = NULL;
    SECStatus          rv;
    int                outlen;

    DBG(DBG_CRYPT, DBG_log("NSS do_aes: enter"));
    ciphermech = CKM_AES_CBC; /*libreswan provides padding*/

    memcpy(&symkey, key, key_size);

    if (symkey == NULL) {
	loglog(RC_LOG_SERIOUS, "do_aes: NSS derived enc key in NULL\n");
	goto out;
    }

    ivitem.type = siBuffer;
    ivitem.data = iv;
    ivitem.len = AES_CBC_BLOCK_SIZE;

    secparam = PK11_ParamFromIV(ciphermech, &ivitem);
    if (secparam == NULL) {
	loglog(RC_LOG_SERIOUS, "do_aes: Failure to set up PKCS11 param (err %d)\n",PR_GetError());
	goto out;
   }

   outlen = 0;
   tmp_buf= PR_Malloc((PRUint32)buf_len);

    if (!enc){
    memcpy(new_iv=iv_bak,(char*) buf + buf_len-AES_CBC_BLOCK_SIZE,AES_CBC_BLOCK_SIZE);
    }

    enccontext = PK11_CreateContextBySymKey(ciphermech, enc? CKA_ENCRYPT : CKA_DECRYPT, symkey, secparam); 
    rv = PK11_CipherOp(enccontext, tmp_buf, &outlen, buf_len, buf, buf_len);
    passert(rv==SECSuccess);
    PK11_DestroyContext(enccontext, PR_TRUE);
    memcpy(buf,tmp_buf,buf_len);  

    if(enc){
    new_iv = (u_int8_t*) buf + buf_len-AES_CBC_BLOCK_SIZE;
    }

    memcpy(iv, new_iv, AES_CBC_BLOCK_SIZE);
    PR_Free(tmp_buf);

out:
 
if (secparam)
    SECITEM_FreeItem(secparam, PR_TRUE);
DBG(DBG_CRYPT, DBG_log("NSS do_aes: exit"));


}
Exemplo n.º 16
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;
}
Exemplo n.º 17
0
/* encrypt a block (XMLSEC_NSS_AES_BLOCK_SIZE), in and out can overlap */
static void
xmlSecNssAesOp(PK11SymKey *aeskey, const xmlSecByte *in, xmlSecByte *out,
	       int enc) {

    CK_MECHANISM_TYPE  cipherMech;
    SECItem*           SecParam = NULL;
    PK11Context*       EncContext = NULL;
    SECStatus          rv;
    int                tmp1_outlen;
    unsigned int       tmp2_outlen;

    xmlSecAssert(in != NULL);
    xmlSecAssert(out != NULL);

    cipherMech = CKM_AES_ECB;
    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, 
		       XMLSEC_NSS_AES_BLOCK_SIZE, (unsigned char *)in, 
		       XMLSEC_NSS_AES_BLOCK_SIZE);
    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, XMLSEC_NSS_AES_BLOCK_SIZE-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;
    }

done:
    if (SecParam) {
	SECITEM_FreeItem(SecParam, PR_TRUE);
    }
    if (EncContext) {
	PK11_DestroyContext(EncContext, PR_TRUE);
    }

}
Exemplo n.º 18
0
static void ike_alg_nss_cbc(const struct encrypt_desc *alg,
			    u_int8_t *in_buf, size_t in_buf_len, PK11SymKey *symkey,
			    u_int8_t *iv, bool enc)
{
	DBG(DBG_CRYPT, DBG_log("NSS ike_alg_nss_cbc: %s - enter", alg->common.name));

	if (symkey == NULL) {
		PASSERT_FAIL("%s - NSS derived enc key in NULL",
			     alg->common.name);
	}

	SECItem ivitem;
	ivitem.type = siBuffer;
	ivitem.data = iv;
	ivitem.len = alg->enc_blocksize;
	SECItem *secparam = PK11_ParamFromIV(alg->common.nss_mechanism, &ivitem);
	if (secparam == NULL) {
		PASSERT_FAIL("%s - Failure to set up PKCS11 param (err %d)",
			     alg->common.name, PR_GetError());
	}

	PK11Context *enccontext;
	enccontext = PK11_CreateContextBySymKey(alg->common.nss_mechanism,
						enc ? CKA_ENCRYPT : CKA_DECRYPT,
						symkey, secparam);
	if (enccontext == NULL) {
		PASSERT_FAIL("%s - PKCS11 context creation failure (err %d)",
			     alg->common.name, PR_GetError());
	}


	/* Output buffer for transformed data.  */
	u_int8_t *out_buf = PR_Malloc((PRUint32)in_buf_len);
	int out_buf_len = 0;

	SECStatus rv = PK11_CipherOp(enccontext, out_buf, &out_buf_len, in_buf_len,
				     in_buf, in_buf_len);
	if (rv != SECSuccess) {
		PASSERT_FAIL("%s - PKCS11 operation failure (err %d)",
			     alg->common.name, PR_GetError());
	}

	PK11_DestroyContext(enccontext, PR_TRUE);

	/*
	 * Update the IV ready for the next call to this function.
	 */
	u_int8_t *new_iv;
	if (enc) {
		/*
		 * The IV for the next encryption call is the last
		 * block of encrypted output data.
		 */
		new_iv = out_buf + out_buf_len - alg->enc_blocksize;
	} else {
		/*
		 * The IV for the next decryption call is the last
		 * block of the encrypted input data.
		 */
		new_iv = in_buf + in_buf_len - alg->enc_blocksize;
	}
	memcpy(iv, new_iv, alg->enc_blocksize);

	/*
	 * Finally, copy the transformed data back to the buffer.  Do
	 * this after extracting the IV.
	 */
	memcpy(in_buf, out_buf, in_buf_len);
	PR_Free(out_buf);

	if (secparam != NULL)
		SECITEM_FreeItem(secparam, PR_TRUE);
	DBG(DBG_CRYPT, DBG_log("NSS ike_alg_nss_cbc: %s - exit", alg->common.name));
}
Exemplo n.º 19
0
int nss_crypto_init(struct crypto_mech_data *mech_props,
                    enum crypto_mech_op crypto_op,
                    struct sss_nss_crypto_ctx *cctx)
{
    CK_ATTRIBUTE_TYPE op;
    int ret;

    switch (crypto_op) {
    case op_encrypt:
        op = CKA_ENCRYPT;
        break;
    case op_decrypt:
        op = CKA_DECRYPT;
        break;
    case op_sign:
        op = CKA_SIGN;
        break;
    default:
        return EFAULT;
    }

    /* turn the raw key into a key object */
    cctx->keyobj = PK11_ImportSymKey(cctx->slot, mech_props->cipher,
                                     PK11_OriginUnwrap, op, cctx->key, NULL);
    if (cctx->keyobj == NULL) {
        DEBUG(SSSDBG_CRIT_FAILURE, "Failure to import key into NSS (err %d)\n",
              PR_GetError());
        ret = EIO;
        goto done;
    }

    if (crypto_op == op_encrypt || crypto_op == op_decrypt) {
        /* turn the raw IV into a initialization vector object */
        cctx->sparam = PK11_ParamFromIV(mech_props->cipher, cctx->iv);
        if (cctx->sparam == NULL) {
            DEBUG(SSSDBG_CRIT_FAILURE,
                  "Failure to set up PKCS11 param (err %d)\n",
                  PR_GetError());
            ret = EIO;
            goto done;
        }
    } else {
        cctx->sparam = SECITEM_AllocItem(NULL, NULL, 0);
        if (cctx->sparam == NULL) {
            DEBUG(SSSDBG_CRIT_FAILURE, "Failure to allocate SECItem\n");
            ret = EIO;
            goto done;
        }
        MAKE_SECITEM(NULL, 0, cctx->sparam);
    }

    /* Create cipher context */
    cctx->ectx = PK11_CreateContextBySymKey(mech_props->cipher, op,
                                            cctx->keyobj, cctx->sparam);
    if (cctx->ectx == NULL) {
        DEBUG(SSSDBG_CRIT_FAILURE, "Cannot create cipher context (err %d)\n",
              PORT_GetError());
        ret = EIO;
        goto done;
    }

    ret = EOK;
done:
    return ret;
}
Exemplo n.º 20
0
static gboolean
purple_aes_cipher_nss_crypt(const guchar *input, guchar *output, size_t len,
	guchar iv[PURPLE_AES_BLOCK_SIZE], guchar key[32], guint key_size,
	CK_ATTRIBUTE_TYPE operation)
{
	PurpleAESCipherNSSContext context;
	CK_MECHANISM_TYPE cipher_mech = CKM_AES_CBC;
	SECItem key_item, iv_item;
	SECStatus ret;
	int outlen = 0;
	unsigned int outlen_tmp = 0;

	memset(&context, 0, sizeof(PurpleAESCipherNSSContext));

	if (NSS_NoDB_Init(NULL) != SECSuccess) {
		purple_debug_error("cipher-aes",
			"NSS_NoDB_Init failed: %d\n", PR_GetError());
		return FALSE;
	}

	context.slot = PK11_GetBestSlot(cipher_mech, NULL);
	if (context.slot == NULL) {
		purple_debug_error("cipher-aes",
			"PK11_GetBestSlot failed: %d\n", PR_GetError());
		return FALSE;
	}

	key_item.type = siBuffer;
	key_item.data = key;
	key_item.len = key_size;
	context.sym_key = PK11_ImportSymKey(context.slot, cipher_mech,
		PK11_OriginUnwrap, CKA_ENCRYPT, &key_item, NULL);
	if (context.sym_key == NULL) {
		purple_debug_error("cipher-aes",
			"PK11_ImportSymKey failed: %d\n", PR_GetError());
		purple_aes_cipher_nss_cleanup(&context);
		return FALSE;
	}

	iv_item.type = siBuffer;
	iv_item.data = iv;
	iv_item.len = PURPLE_AES_BLOCK_SIZE;
	context.sec_param = PK11_ParamFromIV(cipher_mech, &iv_item);
	if (context.sec_param == NULL) {
		purple_debug_error("cipher-aes",
			"PK11_ParamFromIV failed: %d\n", PR_GetError());
		purple_aes_cipher_nss_cleanup(&context);
		return FALSE;
	}

	context.enc_context = PK11_CreateContextBySymKey(cipher_mech, operation,
		context.sym_key, context.sec_param);
	if (context.enc_context == NULL) {
		purple_debug_error("cipher-aes",
			"PK11_CreateContextBySymKey failed: %d\n",
				PR_GetError());
		purple_aes_cipher_nss_cleanup(&context);
		return FALSE;
	}

	ret = PK11_CipherOp(context.enc_context, output, &outlen, len,
			(guchar *)input, len);
	if (ret != SECSuccess) {
		purple_debug_error("cipher-aes",
			"PK11_CipherOp failed: %d\n", PR_GetError());
		purple_aes_cipher_nss_cleanup(&context);
		return FALSE;
	}

	ret = PK11_DigestFinal(context.enc_context, output + outlen, &outlen_tmp,
		len - outlen);
	if (ret != SECSuccess) {
		purple_debug_error("cipher-aes",
			"PK11_DigestFinal failed: %d\n", PR_GetError());
		purple_aes_cipher_nss_cleanup(&context);
		return FALSE;
	}

	purple_aes_cipher_nss_cleanup(&context);

	outlen += outlen_tmp;
	if (outlen != (int)len) {
		purple_debug_error("cipher-aes",
			"resulting length doesn't match: %d (expected: %lu)\n",
			outlen, len);
		return FALSE;
	}

	return TRUE;
}