예제 #1
0
파일: Util.cpp 프로젝트: encukou/pki
TPS_PUBLIC PK11SymKey *Util::DiversifyKey(PK11SymKey *masterKey, Buffer &data, PK11SlotInfo *slot)
{
    PK11SymKey *key = NULL;
    PRStatus status = PR_FAILURE ;
    PK11Context *context = NULL;
#ifdef DES2_WORKAROUND
    unsigned char keyData[24];
#else
    unsigned char keyData[16];
#endif
    SECItem keyItem = { siBuffer, keyData, sizeof keyData };
    SECStatus s;
    int i;
    int len;
    static SECItem noParams = { siBuffer, 0, 0 };

    /* XXX 
           - masterKey could be just a double-length 
             DES Key (16 bytes).
           - we may need to add the first 8 bytes to
             the end to make the key 24 bytes long (DES3 Key)
     */
    context = PK11_CreateContextBySymKey(CKM_DES3_ECB, CKA_ENCRYPT, 
                    masterKey,
                    &noParams);
    if (!context) goto done;

    /* Part 1 */
    s = PK11_CipherOp(context, &keyData[0], &len, 8, &((BYTE*)data)[0], 8);
    if (s != SECSuccess) goto done;

    /* Part 2 */
    s = PK11_CipherOp(context, &keyData[8], &len, 8, &((BYTE*)data)[8], 8);
    if (s != SECSuccess) goto done;

#ifdef DES2_WORKAROUND
    /* Part 3 */
    for(i = 0;i < 8;i++)
    {
        keyData[i+16] = keyData[i];
    }
#endif

    key = PK11_ImportSymKeyWithFlags(
                slot,
                CKM_DES3_ECB, 
                PK11_OriginGenerated,
                CKA_ENCRYPT, 
                &keyItem, CKF_SIGN | CKF_ENCRYPT, PR_FALSE, 0);

    status = PR_SUCCESS;
    
done:

    return key;
}
예제 #2
0
static void
sipe_crypt_ctx_encrypt(PK11Context* EncContext, const guchar *in, gsize length, guchar *out)
{
	int tmp1_outlen;

	PK11_CipherOp(EncContext, out, &tmp1_outlen, length, (unsigned char *)in, length);	
}
예제 #3
0
NS_IMETHODIMP nsStreamCipher::Discard(PRInt32 aLen)
{
  if (!mContext)
    return NS_ERROR_NOT_INITIALIZED;

  unsigned char* output = new unsigned char[aLen];
  if (!output)
    return NS_ERROR_OUT_OF_MEMORY;

  unsigned char* input = new unsigned char[aLen];
  if (!input) {
    delete [] output;
    return NS_ERROR_OUT_OF_MEMORY;
  }

  PRInt32 setLen;

#ifdef DEBUG
  SECStatus rv =
#endif
    PK11_CipherOp(mContext, output, &setLen, aLen, input, aLen);
  NS_ASSERTION(rv == SECSuccess, "failed to encrypt");
  NS_ASSERTION(setLen == aLen, "data length should not change");
  
  delete [] output;
  delete [] input;
  return NS_OK;
}
예제 #4
0
NS_IMETHODIMP nsStreamCipher::Update(const PRUint8 *aData, PRUint32 aLen)
{
  if (!mContext)
    return NS_ERROR_NOT_INITIALIZED;

  unsigned char* output = new unsigned char[aLen];
  if (!output)
    return NS_ERROR_OUT_OF_MEMORY;
  unsigned char* input = (unsigned char*)aData;
  
  PRInt32 setLen;

#ifdef DEBUG
  SECStatus rv =
#endif
    PK11_CipherOp(mContext, output, &setLen, aLen, input, aLen);
  NS_ASSERTION(rv == SECSuccess, "failed to encrypt");
  NS_ASSERTION((PRUint32)setLen == aLen, "data length should not change");

  mValue.Append((const char*)output, aLen);

  delete [] output;

  return NS_OK;
}
예제 #5
0
NS_IMETHODIMP nsStreamCipher::UpdateFromString(const nsACString& aInput)
{
  if (!mContext)
    return NS_ERROR_NOT_INITIALIZED;

  const nsCString& flatInput = PromiseFlatCString(aInput);
  unsigned char* input = (unsigned char*)flatInput.get();
  PRUint32 len = aInput.Length();

  unsigned char* output = new unsigned char[len];
  if (!output)
    return NS_ERROR_OUT_OF_MEMORY;

  PRInt32 setLen;

#ifdef DEBUG
  SECStatus rv =
#endif
    PK11_CipherOp(mContext, output, &setLen, len, input, len);
  NS_ASSERTION(rv == SECSuccess, "failed to encrypt");
  NS_ASSERTION((PRUint32)setLen == len, "data length should not change");

  mValue.Append((const char*)output, len);
  delete [] output;

  return NS_OK;
}
예제 #6
0
파일: Util.cpp 프로젝트: encukou/pki
/*
 * for Secure Messaging in Secure Channel
 */
TPS_PUBLIC PRStatus Util::EncryptData(PK11SymKey *encSessionKey,
			   Buffer &input, Buffer &output)
{
    PRStatus rv = PR_FAILURE;
    SECStatus s = SECFailure;
    //static SECItem noParams = { siBuffer, 0, 0 };
    static unsigned char d[8] = { 0,0,0,0,0,0,0,0 };
    static SECItem ivParams = { siBuffer, d, 8 };
    PK11Context *context = NULL;
    unsigned char result[8];
    int len;
    int i;

    /* this is ECB mode
    context = PK11_CreateContextBySymKey(CKM_DES3_ECB, CKA_ENCRYPT, encSessionKey,
                    &noParams);
    */
    // use CBC mode
    context = PK11_CreateContextBySymKey(CKM_DES3_CBC, CKA_ENCRYPT, encSessionKey,
                    &ivParams);
    if (!context) {
        goto done;
    }

    for(i = 0;i < (int)input.size();i += 8) {
        s = PK11_CipherOp(context, result, &len, 8,
                (unsigned char *)(((BYTE*)input)+i), 8);

        if (s != SECSuccess) {
            goto done;
        }
	output.replace(i, result, 8);
    }

    rv = PR_SUCCESS;
//    RA::Debug("Util::EncryptData", "success");
done:

    //#define VRFY_ENC_SESSION_KEY
    // fix this to use CBC mode later
#ifdef VRFY_ENC_SESSION_KEY
    Buffer enc_key_buffer = Buffer((BYTE *) PK11_GetKeyData(encSessionKey)->data, PK11_GetKeyData(encSessionKey)->len);
        RA::DebugBuffer("Util::EncryptData", "Verifying Encrypted Data",
		&output);
        Buffer out1 = Buffer(16, (BYTE)0);
	PRStatus status = Util::DecryptData(enc_key_buffer, output, out1);
        RA::DebugBuffer("Util::EncryptData", "Decrypted Data",
		&out1);
#endif


    if( context != NULL ) {
        PK11_DestroyContext( context, PR_TRUE );
        context = NULL;
    }

    return rv;
}
예제 #7
0
파일: crypto_nss.c 프로젝트: alama/freerdp
void
crypto_rc4(CryptoRc4 rc4, uint32 len, uint8 * in_data, uint8 * out_data)
{
	int outlen;
	/* valgrind "Invalid read"? See http://groups.google.com/group/mozilla.dev.tech.crypto/browse_thread/thread/361c017b4aa5226f/43badd163bef22f2 */
	SECStatus s = PK11_CipherOp(rc4->context, out_data, &outlen, len, in_data, len);
	check(s, "Error in rc4 encryption");
	ASSERT(outlen == len);
}
예제 #8
0
static int decrypt_nss (
	knet_handle_t knet_h,
	const unsigned char *buf_in,
	const ssize_t buf_in_len,
	unsigned char *buf_out,
	ssize_t *buf_out_len)
{
	struct nsscrypto_instance *instance = knet_h->crypto_instance->model_instance;
	PK11Context*	decrypt_context = NULL;
	SECItem		decrypt_param;
	int		tmp1_outlen = 0;
	unsigned int	tmp2_outlen = 0;
	unsigned char	*salt = (unsigned char *)buf_in;
	unsigned char	*data = salt + SALT_SIZE;
	int		datalen = buf_in_len - SALT_SIZE;
	int		err = -1;

	/* Create cipher context for decryption */
	decrypt_param.type = siBuffer;
	decrypt_param.data = salt;
	decrypt_param.len = SALT_SIZE;

	decrypt_context = PK11_CreateContextBySymKey(cipher_to_nss[instance->crypto_cipher_type],
						     CKA_DECRYPT,
						     instance->nss_sym_key, &decrypt_param);
	if (!decrypt_context) {
		log_err(knet_h, KNET_SUB_NSSCRYPTO, "PK11_CreateContext (decrypt) failed (err %d)",
			   PR_GetError());
		goto out;
	}

	if (PK11_CipherOp(decrypt_context, buf_out, &tmp1_outlen,
			  KNET_DATABUFSIZE_CRYPT, data, datalen) != SECSuccess) {
		log_err(knet_h, KNET_SUB_NSSCRYPTO, "PK11_CipherOp (decrypt) failed (err %d)",
			   PR_GetError());
		goto out;
	}

	if (PK11_DigestFinal(decrypt_context, buf_out + tmp1_outlen, &tmp2_outlen,
			     KNET_DATABUFSIZE_CRYPT - tmp1_outlen) != SECSuccess) {
		log_err(knet_h, KNET_SUB_NSSCRYPTO, "PK11_DigestFinal (decrypt) failed (err %d)",
			   PR_GetError()); 
		goto out;
	}

	*buf_out_len = tmp1_outlen + tmp2_outlen;

	err = 0;

out:
	if (decrypt_context) {
		PK11_DestroyContext(decrypt_context, PR_TRUE);
	}

	return err;
}
예제 #9
0
파일: Util.cpp 프로젝트: encukou/pki
// this one takes PK11SymKey instead
TPS_PUBLIC PRStatus Util::DecryptData(PK11SymKey* enc_key, Buffer &input, Buffer &output)
{
    PRStatus rv = PR_FAILURE;

    PK11Context *context = NULL;
    int i;
    SECStatus s = SECFailure;
    int len;
    //    static SECItem noParams = { siBuffer, 0, 0 };
    static unsigned char d[8] = { 0,0,0,0,0,0,0,0 };
    static SECItem ivParams = { siBuffer, d, 8 };
    unsigned char result[8];

    if( ! enc_key ) {
        goto done;
    }

    context = PK11_CreateContextBySymKey(CKM_DES3_CBC, CKA_DECRYPT, enc_key,
                    &ivParams);
    if (!context) {
        goto done;
    }

    for(i = 0;i < (int)input.size();i += 8) {
        s = PK11_CipherOp(context, result, &len, 8,
                (unsigned char *)(((BYTE *)input)+i), 8);

        if (s != SECSuccess) {
            goto done;
        }
	output.replace(i, result, 8);
    }

    rv = PR_SUCCESS;

done:

    if( context != NULL ) {
        PK11_DestroyContext( context, PR_TRUE );
        context = NULL;
    }

    return rv;
}
SVRCOREError
SVRCORE_Pk11StoreGetPin(char **out, SVRCOREPk11PinStore *store)
{
  SVRCOREError err = SVRCORE_Success;
  unsigned char *plain;
  SECStatus rv;
  PK11Context *ctx = 0;
  int outLen;

  do {
    plain = (unsigned char *)malloc(store->length);
    if (!plain) { err = SVRCORE_NoMemory_Error; break; }

    ctx = PK11_CreateContextBySymKey(store->mech->type, CKA_DECRYPT,
              store->key, store->params);
    if (!ctx) { err = SVRCORE_System_Error; break; }

    rv = PK11_CipherOp(ctx, plain, &outLen, store->length,
           store->crypt, store->length);
    if (rv) break;

    rv = PK11_Finalize(ctx);
    if (rv) break;
  } while(0);

  if (ctx) PK11_DestroyContext(ctx, PR_TRUE);

  if (rv)
  {
    err = SVRCORE_System_Error;
    memset(plain, 0, store->length);
    free(plain);
    plain = 0;
  }

  *out = (char *)plain;
  return err;
}
예제 #11
0
int
Pk11StoreGetPin(char **out, Pk11PinStore *store)
{
    int err = PIN_SUCCESS;
    unsigned char *plain;
    SECStatus rv = SECSuccess;
    PK11Context *ctx = 0;
    int outLen;

    do {
        plain = (unsigned char *)malloc(store->length);
        if (!plain) { err = PIN_NOMEMORY; break; }

        ctx = PK11_CreateContextBySymKey(store->mech->type, CKA_DECRYPT,
                  store->key, store->params);
        if (!ctx) { err = PIN_SYSTEMERROR; break; }

        rv = PK11_CipherOp(ctx, plain, &outLen, store->length,
               store->crypt, store->length);
        if (rv) break;

        rv = PK11_Finalize(ctx);
        if (rv) break;
    } while(0);

    if (ctx) PK11_DestroyContext(ctx, PR_TRUE);

    if (rv)
    {
        err = PIN_SYSTEMERROR;
        memset(plain, 0, store->length);
        free(plain);
        plain = 0;
    }

    *out = (char *)plain;
    return err;
}
예제 #12
0
/**
 * @brief Decrypt data provided by in, write it to out.
 * @note The number of bytes written will be written to outlen. If
 *       out is NULL, outlen will contain the maximum size of the
 *       buffer needed to hold the data, including any data
 *       generated by apr_crypto_block_decrypt_finish below. If *out points
 *       to NULL, a buffer sufficiently large will be created from
 *       the pool provided. If *out points to a not-NULL value, this
 *       value will be used as a buffer instead.
 * @param out Address of a buffer to which data will be written,
 *        see note.
 * @param outlen Length of the output will be written here.
 * @param in Address of the buffer to read.
 * @param inlen Length of the buffer to read.
 * @param ctx The block context to use.
 * @return APR_ECRYPT if an error occurred. Returns APR_ENOTIMPL if
 *         not implemented.
 */
static apr_status_t crypto_block_decrypt(unsigned char **out,
        apr_size_t *outlen, const unsigned char *in, apr_size_t inlen,
        apr_crypto_block_t *block)
{

    unsigned char *buffer;
    int outl = (int) *outlen;
    SECStatus s;
    if (!out) {
        *outlen = inlen + block->blockSize;
        return APR_SUCCESS;
    }
    if (!*out) {
        buffer = apr_palloc(block->pool, inlen + block->blockSize);
        if (!buffer) {
            return APR_ENOMEM;
        }
        apr_crypto_clear(block->pool, buffer, inlen + block->blockSize);
        *out = buffer;
    }

    s = PK11_CipherOp(block->ctx, *out, &outl, inlen, (unsigned char*) in,
            inlen);
    if (s != SECSuccess) {
        PRErrorCode perr = PORT_GetError();
        if (perr) {
            block->f->result->rc = perr;
            block->f->result->msg = PR_ErrorToName(perr);
        }
        return APR_ECRYPT;
    }
    *outlen = outl;

    return APR_SUCCESS;

}
예제 #13
0
파일: ssl_nss.c 프로젝트: MrSam/bitlbee
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;
}
예제 #14
0
/*
 * CreatePk11PinStore
 */
int
CreatePk11PinStore(Pk11PinStore **out, const char *tokenName, const char *pin)
{
    int err = PIN_SUCCESS;
    Pk11PinStore *store;

    do {

        store = (Pk11PinStore*)malloc(sizeof(Pk11PinStore));
        if (store == 0) { err = PIN_NOMEMORY; break; }

        /* Low-level init */
        store->key = 0;
        store->params = 0;
        store->crypt = 0;

        /* Use the tokenName to find a PKCS11 slot */
        store->slot = PK11_FindSlotByName((char *)tokenName);
        if (store->slot == 0) { err = PIN_NOSUCHTOKEN; break; }

        /* Check the password/PIN.  This allows access to the token */
        {
            SECStatus rv = PK11_CheckUserPassword(store->slot, (char *)pin);

            if (rv == SECSuccess)
                ;
            else if (rv == SECWouldBlock)
            {
                /* NSS returns a blocking error when the pin is wrong */
                err = PIN_INCORRECTPW;
                break;
            }
            else
            {
                err = PIN_SYSTEMERROR;
                break;
            }
        }

        /* Find the mechanism that this token can do */
        {
            const mech_item *tp;

            store->mech = 0;
            for(tp = table;tp < &table[MECH_TABLE_SIZE];tp++)
            {
                if (PK11_DoesMechanism(store->slot, tp->type))
                {
                    store->mech = (mech_item *)tp;
                    break;
                }
            }
            /* Default to a mechanism (probably on the internal token */
            if (store->mech == 0) {
                store->mech = &dflt_mech;
            }
        }

        /* Generate a key and parameters to do the encryption */
#if NSS_VMAJOR >= 3 && (NSS_VMINOR <= 9 || (NSS_VMINOR <= 10 && NSS_VPATCH == 0))
        store->key = PK11_KeyGen(store->slot, store->mech->type,
                       0, 0, 0);
#else
        store->key = PK11_TokenKeyGenWithFlags(store->slot, store->mech->type,
                     NULL, 0, NULL, CKF_ENCRYPT|CKF_DECRYPT, PR_FALSE, NULL);
#endif
        if (store->key == 0)
        {
            /* PR_SetError(xxx); */
            err = PIN_SYSTEMERROR;
            break;
        }

        store->params = PK11_GenerateNewParam(store->mech->type, store->key);
        if (store->params == 0)
        {
            err = PIN_SYSTEMERROR;
            break;
        }

        /* Compute the size of the encrypted data including necessary padding */
        {
            int blocksize = PK11_GetBlockSize(store->mech->type, 0);

            store->length = strlen(pin)+1;

            /* Compute padded size - 0 means stream cipher */
            if (blocksize != 0)
            {
                store->length += blocksize - (store->length % blocksize);
            }

            store->crypt = (unsigned char *)malloc(store->length);
            if (!store->crypt) { err = PIN_NOMEMORY; break; }
        }

        /* Encrypt */
        {
            unsigned char *plain;
            PK11Context *ctx;
            SECStatus rv;
            int outLen;

            plain = (unsigned char *)malloc(store->length);
            if (!plain) { err = PIN_NOMEMORY; break; }

            /* Pad with 0 bytes */
            memset(plain, 0, store->length);
            strcpy((char *)plain, pin);

            ctx = PK11_CreateContextBySymKey(store->mech->type, CKA_ENCRYPT,
                    store->key, store->params);
            if (!ctx) { err = PIN_SYSTEMERROR; break; }

            do {
                rv = PK11_CipherOp(ctx, store->crypt, &outLen, store->length,
                       plain, store->length);
                if (rv) break;

                rv = PK11_Finalize(ctx);
            } while(0);

            PK11_DestroyContext(ctx, PR_TRUE);
            memset(plain, 0, store->length);
            free(plain);

            if (rv) err = PIN_SYSTEMERROR;
        }
    } while(0);

    if (err)
    {
        DestroyPk11PinStore(store);
        store = 0;
    }

    *out = store;
    return err;
}
예제 #15
0
/* the content of an encrypted data content info is decrypted.
 * it is assumed that for encrypted data, that the data has already
 * been set and is in the "encContent" field of the content info.
 *
 * cinfo is the content info to decrypt
 *
 * key is the key with which to perform the decryption.  if the
 *     algorithm is a password based encryption algorithm, the
 *     key is actually a password which will be processed per
 *     PKCS #5.
 * 
 * in the event of an error, SECFailure is returned.  SECSuccess
 * indicates a success.
 */
SECStatus 
SEC_PKCS7DecryptContents(PRArenaPool *poolp,
			 SEC_PKCS7ContentInfo *cinfo,
			 SECItem *key,
			 void *wincx)
{
    SECAlgorithmID *algid = NULL;
    SECStatus rv = SECFailure;
    SECItem *result = NULL, *dest, *src;
    void *mark;

    PK11SymKey *eKey = NULL;
    PK11SlotInfo *slot = NULL;
    CK_MECHANISM_TYPE cryptoMechType;
    void *cx;
    SECItem *c_param = NULL;
    int bs;

    if((cinfo == NULL) || (key == NULL))
	return SECFailure;

    if(SEC_PKCS7ContentType(cinfo) != SEC_OID_PKCS7_ENCRYPTED_DATA)
	return SECFailure;

    algid = SEC_PKCS7GetEncryptionAlgorithm(cinfo);	
    if(algid == NULL)
	return SECFailure;

    if(poolp == NULL)
	poolp = cinfo->poolp;

    mark = PORT_ArenaMark(poolp);
    
    src = &cinfo->content.encryptedData->encContentInfo.encContent;
    dest = &cinfo->content.encryptedData->encContentInfo.plainContent;
    dest->data = (unsigned char*)PORT_ArenaZAlloc(poolp, (src->len + 64));
    dest->len = (src->len + 64);
    if(dest->data == NULL) {
	rv = SECFailure;
	goto loser;
    }

    slot = PK11_GetInternalKeySlot();
    if(slot == NULL) {
	rv = SECFailure;
	goto loser;
    }

    eKey = PK11_PBEKeyGen(slot, algid, key, PR_FALSE, wincx);
    if(eKey == NULL) {
	rv = SECFailure;
	goto loser;
    }
    
    cryptoMechType = PK11_GetPBECryptoMechanism(algid, &c_param, key);
    if (cryptoMechType == CKM_INVALID_MECHANISM) {
	rv = SECFailure;
	goto loser;
    }

    cx = PK11_CreateContextBySymKey(cryptoMechType, CKA_DECRYPT,
		    		    eKey, c_param);
    if(cx == NULL) {
	rv = SECFailure;
	goto loser;
    }

    rv = PK11_CipherOp((PK11Context*)cx, dest->data, (int *)(&dest->len), 
		       (int)(src->len + 64), src->data, (int)src->len);
    PK11_DestroyContext((PK11Context *)cx, PR_TRUE);

    bs = PK11_GetBlockSize(cryptoMechType, c_param);
    if(bs) {
	/* check for proper badding in block algorithms.  this assumes
	 * RC2 cbc or a DES cbc variant.  and the padding is thus defined
	 */
	if(((int)dest->data[dest->len-1] <= bs) && 
	   ((int)dest->data[dest->len-1] > 0)) {
	    dest->len -= (int)dest->data[dest->len-1];
	} else {
	    rv = SECFailure;
	    /* set an error ? */
	}
    } 

loser:
    /* let success fall through */
    if(result != NULL)
	SECITEM_ZfreeItem(result, PR_TRUE);

    if(rv == SECFailure)
	PORT_ArenaRelease(poolp, mark);
    else
	PORT_ArenaUnmark(poolp, mark);

    if(eKey != NULL)
	PK11_FreeSymKey(eKey);

    if(slot != NULL)
	PK11_FreeSlot(slot);

    if(c_param != NULL) 
	SECITEM_ZfreeItem(c_param, PR_TRUE);
	
    return rv;
}
예제 #16
0
/* the content of an encrypted data content info is encrypted.
 * it is assumed that for encrypted data, that the data has already
 * been set and is in the "plainContent" field of the content info.
 *
 * cinfo is the content info to encrypt
 *
 * key is the key with which to perform the encryption.  if the
 *     algorithm is a password based encryption algorithm, the
 *     key is actually a password which will be processed per
 *     PKCS #5.
 * 
 * in the event of an error, SECFailure is returned.  SECSuccess
 * indicates a success.
 */
SECStatus 
SEC_PKCS7EncryptContents(PRArenaPool *poolp,
			 SEC_PKCS7ContentInfo *cinfo,
			 SECItem *key,
			 void *wincx)
{
    SECAlgorithmID *algid 	= NULL;
    SECItem *       result 	= NULL;
    SECItem *       src;
    SECItem *       dest;
    SECItem *       blocked_data = NULL;
    void *          mark;
    void *          cx;
    PK11SymKey *    eKey 	= NULL;
    PK11SlotInfo *  slot 	= NULL;

    CK_MECHANISM_TYPE cryptoMechType;
    int             bs;
    SECStatus       rv 		= SECFailure;
    SECItem         *c_param = NULL;

    if((cinfo == NULL) || (key == NULL))
	return SECFailure;

    if(SEC_PKCS7ContentType(cinfo) != SEC_OID_PKCS7_ENCRYPTED_DATA)
	return SECFailure;

    algid = SEC_PKCS7GetEncryptionAlgorithm(cinfo);	
    if(algid == NULL)
	return SECFailure;

    if(poolp == NULL)
	poolp = cinfo->poolp;

    mark = PORT_ArenaMark(poolp);
    
    src = &cinfo->content.encryptedData->encContentInfo.plainContent;
    dest = &cinfo->content.encryptedData->encContentInfo.encContent;
    dest->data = (unsigned char*)PORT_ArenaZAlloc(poolp, (src->len + 64));
    dest->len = (src->len + 64);
    if(dest->data == NULL) {
	rv = SECFailure;
	goto loser;
    }

    slot = PK11_GetInternalKeySlot();
    if(slot == NULL) {
	rv = SECFailure;
	goto loser;
    }

    eKey = PK11_PBEKeyGen(slot, algid, key, PR_FALSE, wincx);
    if(eKey == NULL) {
	rv = SECFailure;
	goto loser;
    }
    
    cryptoMechType = PK11_GetPBECryptoMechanism(algid, &c_param, key);
    if (cryptoMechType == CKM_INVALID_MECHANISM) {
	rv = SECFailure;
	goto loser;
    }

    /* block according to PKCS 8 */
    bs = PK11_GetBlockSize(cryptoMechType, c_param);
    rv = SECSuccess;
    if(bs) {
	char pad_char;
	pad_char = (char)(bs - (src->len % bs));
	if(src->len % bs) {
	    rv = SECSuccess;
	    blocked_data = PK11_BlockData(src, bs);
	    if(blocked_data) {
		PORT_Memset((blocked_data->data + blocked_data->len 
			    - (int)pad_char), 
			    pad_char, (int)pad_char);
	    } else {
		rv = SECFailure;
		goto loser;
	    }
	} else {
	    blocked_data = SECITEM_DupItem(src);
	    if(blocked_data) {
		blocked_data->data = (unsigned char*)PORT_Realloc(
						  blocked_data->data,
						  blocked_data->len + bs);
		if(blocked_data->data) {
		    blocked_data->len += bs;
		    PORT_Memset((blocked_data->data + src->len), (char)bs, bs);
		} else {
		    rv = SECFailure;
		    goto loser;
		}
	    } else {
		rv = SECFailure;
		goto loser;
	    }
	 }
    } else {
	blocked_data = SECITEM_DupItem(src);
	if(!blocked_data) {
	    rv = SECFailure;
	    goto loser;
	}
    }

    cx = PK11_CreateContextBySymKey(cryptoMechType, CKA_ENCRYPT,
		    		    eKey, c_param);
    if(cx == NULL) {
	rv = SECFailure;
	goto loser;
    }

    rv = PK11_CipherOp((PK11Context*)cx, dest->data, (int *)(&dest->len), 
		       (int)(src->len + 64), blocked_data->data, 
		       (int)blocked_data->len);
    PK11_DestroyContext((PK11Context*)cx, PR_TRUE);

loser:
    /* let success fall through */
    if(blocked_data != NULL)
	SECITEM_ZfreeItem(blocked_data, PR_TRUE);

    if(result != NULL)
	SECITEM_ZfreeItem(result, PR_TRUE);

    if(rv == SECFailure)
	PORT_ArenaRelease(poolp, mark);
    else 
	PORT_ArenaUnmark(poolp, mark);

    if(eKey != NULL)
	PK11_FreeSymKey(eKey);

    if(slot != NULL)
	PK11_FreeSlot(slot);

    if(c_param != NULL) 
	SECITEM_ZfreeItem(c_param, PR_TRUE);
	
    return rv;
}
예제 #17
0
파일: Util.cpp 프로젝트: encukou/pki
TPS_PUBLIC PRStatus Util::ComputeMAC(PK11SymKey *key, Buffer &x_input, 
		const Buffer &icv, Buffer &output)
{
    PRStatus rv = PR_SUCCESS;
    PK11Context *context = NULL;
//    NetkeyICV temp;
    unsigned char result[8];
    int i;
    SECStatus s;
    int len;
#ifdef USE_DESMAC
    CK_ULONG macLen = sizeof result;
    SECItem params = { siBuffer, (unsigned char *)&macLen, sizeof macLen };
#endif
    static SECItem noParams = { siBuffer, 0, 0 };
    static unsigned char macPad[] = {
        0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
    };
    BYTE *input = (BYTE *) x_input;	
    int inputLen = x_input.size();

#ifdef USE_DESMAC
    context = PK11_CreateContextBySymKey(CKM_DES3_MAC_GENERAL, CKA_SIGN,
                                key, &params);
    if (!context) { rv = PR_FAILURE; goto done; }

    s = PK11_DigestBegin(context);
    if (s != SECSuccess) { rv = PR_FAILURE; goto done; }

    s = PK11_DigestOp(context, icv, 8);
    if (s != SECSuccess) { rv = PR_FAILURE; goto done; }

    while(inputLen >= 8)
    {
        s = PK11_DigestOp(context, input, 8);
        if (s != SECSuccess) { rv = PR_FAILURE; goto done; }

        input += 8;
        inputLen -= 8;
    }

    for (i = 0;i < inputLen;i++)
    {
        result[i] = input[i];
    }

    input = macPad;
    for(;i < 8;i++)
    {
        result[i] = *input++;
    }

    s = PK11_DigestOp(context, result, sizeof result);
    if (s != SECSuccess) { rv = PR_FAILURE; goto done; }

    s = PK11_DigestFinal(context, output, (unsigned int *)&len, sizeof output);
    if (1 != SECSuccess) { rv = PR_FAILURE; goto done; }

#else

    context = PK11_CreateContextBySymKey(CKM_DES3_ECB, CKA_ENCRYPT, key, &noParams);
    if (!context) { rv = PR_FAILURE; goto done; }

    memcpy(result, icv, sizeof result);

    /* Process whole blocks */
    while(inputLen >= 8)
    {
        for(i = 0;i < 8;i++)
        {
            result[i] ^= input[i];
        }

        s = PK11_CipherOp(context, result, &len, sizeof result, result, sizeof result);
        if (s != SECSuccess) { rv = PR_FAILURE; goto done; }
        if (len != sizeof result) /* assert? */
        {
            //PR_SetError(PR_UNKNOWN_ERROR, 0);
            rv = PR_FAILURE;
            goto done;
        }

        input += 8;
        inputLen -= 8;
    }

    /*
     * Fold in remaining data (if any)
     * Set i to number of bytes processed
     */
    for(i = 0;i < inputLen;i++)
    {
        result[i] ^= input[i];
    }

    /*
     * Fill remainder of last block. There
     * will be at least one byte handled here.
     */
    input = macPad;
    while(i < 8)
    {
        result[i] ^= *input++;
        i++;
    }

    s = PK11_CipherOp(context, result, &len, sizeof result, result, sizeof result);
    if (s != SECSuccess) { rv = PR_FAILURE; goto done; }
    if (len != sizeof result)
    {
        //PR_SetError(PR_UNKNOWN_ERROR, 0);
        rv = PR_FAILURE;
        goto done;
    }

    output.replace(0, result, sizeof result);
#endif

done:
    if( context != NULL )
    {
        PK11_Finalize( context );
        PK11_DestroyContext( context, PR_TRUE );
        context = NULL;
    }
    memset(result, 0, sizeof result);

    return rv;
} /* ComputeMAC */
예제 #18
0
파일: kw_aes.c 프로젝트: Arcenciel/DDReader
/* 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);
    }

}
예제 #19
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"));


}
예제 #20
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;
}
/*
 * SVRCORE_CreatePk11PinStore
 */
SVRCOREError
SVRCORE_CreatePk11PinStore(
  SVRCOREPk11PinStore **out,
  const char *tokenName, const char *pin)
{
  SVRCOREError err;
  SVRCOREPk11PinStore *store;

  do {
    err = SVRCORE_Success;

    store = (SVRCOREPk11PinStore*)malloc(sizeof *store);
    if (store == 0) { err = SVRCORE_NoMemory_Error; break; }

    /* Low-level init */
    store->slot = 0;
    store->key = 0;
    store->params = 0;
    store->crypt = 0;

    /* Use the tokenName to find a PKCS11 slot */
    store->slot = PK11_FindSlotByName((char *)tokenName);
    if (store->slot == 0) { err = SVRCORE_NoSuchToken_Error; break; }

    /* Check the password/PIN.  This allows access to the token */
    {
      SECStatus rv = PK11_CheckUserPassword(store->slot, (char *)pin);

      if (rv == SECSuccess)
        ;
      else if (rv == SECWouldBlock)
      {
        err = SVRCORE_IncorrectPassword_Error;
        break;
      }
      else
      {
        err = SVRCORE_System_Error;
        break;
      }
    }

    /* Find the mechanism that this token can do */
    {
      const mech_item *tp;

      store->mech = 0;
      for(tp = table;tp < &table[MECH_TABLE_SIZE];tp++)
      {
        if (PK11_DoesMechanism(store->slot, tp->type))
        {
          store->mech = tp;
          break;
        }
      }
      /* Default to a mechanism (probably on the internal token */
      if (store->mech == 0)
        store->mech = &dflt_mech;
    }

    /* Generate a key and parameters to do the encryption */
    store->key = PK11_TokenKeyGenWithFlags(store->slot, store->mech->type,
                 0, 0, 0, CKF_ENCRYPT|CKF_DECRYPT,
                 0, 0);
    if (store->key == 0)
    {
      /* PR_SetError(xxx); */
      err = SVRCORE_System_Error;
      break;
    }

    store->params = PK11_GenerateNewParam(store->mech->type, store->key);
    if (store->params == 0)
    {
      err = SVRCORE_System_Error;
      break;
    }

    /* Compute the size of the encrypted data including necessary padding */
    {
      int blocksize = PK11_GetBlockSize(store->mech->type, 0);

      store->length = strlen(pin)+1;

      /* Compute padded size - 0 means stream cipher */
      if (blocksize != 0)
      {
        store->length += blocksize - (store->length % blocksize);
      }

      store->crypt = (unsigned char *)malloc(store->length);
      if (!store->crypt) { err = SVRCORE_NoMemory_Error; break; }
    }

    /* Encrypt */
    {
      unsigned char *plain;
      PK11Context *ctx;
      SECStatus rv;
      int outLen;

      plain = (unsigned char *)malloc(store->length);
      if (!plain) { err = SVRCORE_NoMemory_Error; break; }

      /* Pad with 0 bytes */
      memset(plain, 0, store->length);
      strcpy((char *)plain, pin);

      ctx = PK11_CreateContextBySymKey(store->mech->type, CKA_ENCRYPT,
              store->key, store->params);
      if (!ctx) { err = SVRCORE_System_Error; break; }

      do {
        rv = PK11_CipherOp(ctx, store->crypt, &outLen, store->length,
               plain, store->length);
        if (rv) break;

        rv = PK11_Finalize(ctx);
      } while(0);

      PK11_DestroyContext(ctx, PR_TRUE);
      memset(plain, 0, store->length);
      free(plain);

      if (rv) err = SVRCORE_System_Error;
    }
  } while(0);

  if (err)
  {
    SVRCORE_DestroyPk11PinStore(store);
    store = 0;
  }

  *out = store;
  return err;
}
예제 #22
0
파일: Util.cpp 프로젝트: encukou/pki
TPS_PUBLIC PRStatus Util::EncryptData(Buffer &kek_key, Buffer &input, Buffer &output)
{
    PRStatus rv = PR_FAILURE;

    PK11SymKey *master = NULL;
    PK11SlotInfo *slot = PK11_GetInternalKeySlot();
    PK11Context *context = NULL;
    int i;
    SECStatus s = SECFailure;
    int len;
    static SECItem noParams = { siBuffer, 0, 0 };
#ifdef DES2_WORKAROUND
    unsigned char masterKeyData[24];
#else
    unsigned char masterKeyData[16];
#endif
    SECItem masterKeyItem = {siBuffer, masterKeyData, sizeof(masterKeyData) };
    unsigned char result[8];

    // convert 16-byte to 24-byte triple-DES key
    memcpy(masterKeyData, (BYTE*)kek_key, 16);
#ifdef DES2_WORKAROUND
    memcpy(masterKeyData+16, (BYTE*)kek_key, 8);
#endif

    master = PK11_ImportSymKeyWithFlags(slot, CKM_DES3_ECB,
                   PK11_OriginGenerated, CKA_ENCRYPT, &masterKeyItem,
                   CKF_ENCRYPT, PR_FALSE, 0);
    if( ! master ) {
        goto done;
    }

    context = PK11_CreateContextBySymKey(CKM_DES3_ECB, CKA_ENCRYPT, master,
                    &noParams);
    if (!context) {
        goto done;
    }

    for(i = 0;i < (int)input.size();i += 8) {
        s = PK11_CipherOp(context, result, &len, 8,
                (unsigned char *)(((BYTE*)input)+i), 8);

        if (s != SECSuccess) {
            goto done;
        }
	output.replace(i, result, 8);
    }

    rv = PR_SUCCESS;

done:

    memset(masterKeyData, 0, sizeof masterKeyData);
    if( context != NULL ) {
        PK11_DestroyContext( context, PR_TRUE );
        context = NULL;
    }
    if( slot != NULL ) {
        PK11_FreeSlot( slot );
        slot = NULL;
    }
    if( master != NULL ) {
        PK11_FreeSymKey( master );
        master = NULL;
    }

    return rv;
}
예제 #23
0
파일: pem.c 프로젝트: intliang/libreswan
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"));
}
예제 #24
0
파일: Util.cpp 프로젝트: encukou/pki
TPS_PUBLIC PK11SymKey *Util::DeriveKey(const Buffer& permKey,
                        const Buffer& hostChallenge,
                        const Buffer& cardChallenge)
{
    PK11SymKey *key = NULL, *master = NULL;
    PK11SlotInfo *slot = PK11_GetInternalKeySlot();
    PK11Context *context = NULL;
    unsigned char derivationData[16];
#ifdef DES2_WORKAROUND
    unsigned char keyData[24];
#else
    unsigned char keyData[16];
#endif
    int i;
    SECStatus s;
    int len;
    SECItem keyItem = { siBuffer, keyData, sizeof keyData };
    static SECItem noParams = { siBuffer, 0, 0 };
    BYTE masterKeyData[24];
    SECItem masterKeyItem = {siBuffer, masterKeyData, sizeof(masterKeyData) };

    // convert 16-byte to 24-byte triple-DES key
    memcpy(masterKeyData, permKey, 16);
    memcpy(masterKeyData+16, permKey, 8);

    master = PK11_ImportSymKeyWithFlags(slot, CKM_DES3_ECB,
                   PK11_OriginGenerated, CKA_ENCRYPT, &masterKeyItem,
                   CKF_ENCRYPT, PR_FALSE, 0);
    if( ! master ) goto done;

    for(i = 0;i < 4;i++)
    {
        derivationData[i] = cardChallenge[i+4];
        derivationData[i+4] = hostChallenge[i];
        derivationData[i+8] = cardChallenge[i];
        derivationData[i+12] = hostChallenge[i+4];
    }
    context = PK11_CreateContextBySymKey(CKM_DES3_ECB, CKA_ENCRYPT, master,
                    &noParams);
    if (!context) goto done;

    /* Part 1 */
    s = PK11_CipherOp(context, &keyData[0], &len, 8, &derivationData[0], 8);
    if (s != SECSuccess) goto done;

    /* Part 2 */
    s = PK11_CipherOp(context, &keyData[8], &len, 8, &derivationData[8], 8);
    if (s != SECSuccess) goto done;

#ifdef DES2_WORKAROUND
    /* Part 3 */
    for(i = 0;i < 8;i++)
    {
        keyData[i+16] = keyData[i];
    }
#endif

    key = PK11_ImportSymKeyWithFlags(slot, CKM_DES3_ECB, PK11_OriginGenerated,
                   CKA_ENCRYPT, &keyItem, CKF_SIGN | CKF_ENCRYPT, PR_FALSE, 0);

done:
    memset(keyData, 0, sizeof keyData);
    if( context != NULL ) {
        PK11_DestroyContext( context, PR_TRUE );
        context = NULL;
    }
    if( slot != NULL ) {
        PK11_FreeSlot( slot );
        slot = NULL;
    }
    if( master != NULL ) {
        PK11_FreeSymKey( master );
        master = NULL;
    }

    return key;
}
예제 #25
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;
}
예제 #26
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));
}
예제 #27
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;
}
예제 #28
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;
}
예제 #29
0
파일: kw_aes.c 프로젝트: Arcenciel/DDReader
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);
}
예제 #30
0
파일: Util.cpp 프로젝트: encukou/pki
TPS_PUBLIC PRStatus Util::ComputeKeyCheck(const Buffer& newKey, Buffer& output)
{
    PK11SymKey *key = NULL;
    PRStatus status = PR_FAILURE ;
    PK11SlotInfo *slot = PK11_GetInternalKeySlot();
    PK11Context *context = NULL;
    SECStatus s = SECFailure;
    int len;
    static SECItem noParams = { siBuffer, 0, 0 };
#ifdef DES2_WORKAROUND
    unsigned char keyData[24];
#else
    unsigned char keyData[16];
#endif
    SECItem keyItem = {siBuffer, keyData, sizeof(keyData) };
    unsigned char value[8];
    // convert 16-byte to 24-byte triple-DES key
    memcpy(keyData, newKey, 16);
#ifdef DES2_WORKAROUND
    memcpy(keyData+16, newKey, 8);
#endif

    memset(value, 0, sizeof value);

    key = PK11_ImportSymKeyWithFlags(slot, CKM_DES3_ECB,
                   PK11_OriginGenerated, CKA_ENCRYPT, &keyItem,
                   CKF_ENCRYPT, PR_FALSE, 0);
    if( ! key ) {
        goto done;
    }

    context = PK11_CreateContextBySymKey(CKM_DES3_ECB, CKA_ENCRYPT, key,
                    &noParams);
    if (!context) {
        goto done;
    }
    s = PK11_CipherOp(context, &value[0], &len, 8, &value[0], 8);
    if (s != SECSuccess) {
        goto done;
    }

    output.resize(3);
    output.replace(0, value, 3);

    status = PR_SUCCESS;
done:
    memset(keyData, 0, sizeof keyData);
    if( context != NULL ) {
        PK11_DestroyContext( context, PR_TRUE );
        context = NULL;
    }
    if( slot != NULL ) {
        PK11_FreeSlot( slot );
        slot = NULL;
    }
    if( key != NULL ) {
        PK11_FreeSymKey( key );
        key = NULL;
    }

    return status;
}