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); }
int main(int argc, char **argv) { CK_MECHANISM_TYPE hashMech; PK11SlotInfo* slot = NULL; PK11SymKey* SymKey = NULL; SECItem SecParam; PK11Context* HashContext = NULL; SECItem keyItem; SECStatus rv, rv1, rv2; unsigned char buf1[1024], buf2[1024]; char data[1024]; int i; unsigned int tmp2_outlen; /* Initialize NSS * * If your application code has already initialized NSS, you can skip it * * here. * * This code uses the simplest of the Init functions, which does not * * require a NSS database to exist * */ rv = NSS_NoDB_Init("."); if (rv != SECSuccess) { fprintf(stderr, "NSS initialization failed (err %d)\n", PR_GetError()); goto out; } /* choose mechanism: CKM_DES_CBC_PAD, CKM_DES3_ECB, CKM_DES3_CBC..... * * Note that some mechanisms (*_PAD) imply the padding is handled for you * * by NSS. If you choose something else, then data padding is the * * application's responsibility * */ hashMech = CKM_SHA_1_HMAC; slot = PK11_GetBestSlot(hashMech, NULL); /* slot = PK11_GetInternalKeySlot(); is a simpler alternative but in * * theory, it *may not* return the optimal slot for the operation. For * * DES ops, Internal slot is typically the best slot * */ if (slot == NULL) { fprintf(stderr, "Unable to find security device (err %d)\n", PR_GetError()); goto out; } /* NSS passes blobs around as SECItems. These contain a pointer to * * data and a length. Turn the raw key into a SECItem. */ keyItem.type = siBuffer; keyItem.data = gKey; keyItem.len = sizeof(gKey); /* Turn the raw key into a key object. We use PK11_OriginUnwrap * * to indicate the key was unwrapped - which is what should be done * * normally anyway - using raw keys isn't a good idea */ SymKey = PK11_ImportSymKey(slot, hashMech, PK11_OriginUnwrap, CKA_SIGN, &keyItem, NULL); if (SymKey == NULL) { fprintf(stderr, "Failure to import key into NSS (err %d)\n", PR_GetError()); goto out; } SecParam.type = siBuffer; SecParam.data = 0; SecParam.len = 0; /* sample data we'll hash */ strcpy(data, "Hash me!"); fprintf(stderr, "Clear Data: %s\n", data); /* ========================= START SECTION ============================= */ /* If using the the same key and iv over and over, stuff before this */ /* section and after this section needs to be done only ONCE */ /* Create cipher context */ HashContext = PK11_CreateContextBySymKey(hashMech, CKA_SIGN, SymKey, &SecParam); if (!HashContext) { fprintf(stderr, "no hash context today?\n"); goto out; } if (PK11_DigestBegin(HashContext) != SECSuccess) { fprintf(stderr, "hash doesn't begin?\n"); goto out; } rv1 = PK11_DigestOp(HashContext, (unsigned char *)data, strlen(data)+1); rv2 = PK11_DigestFinal(HashContext, buf2, &tmp2_outlen, SHA1_BLOCK_LENGTH); PK11_DestroyContext(HashContext, PR_TRUE); if (rv1 != SECSuccess || rv2 != SECSuccess) goto out; fprintf(stderr, "Hash Data: "); for (i=0; i<tmp2_outlen; i++) fprintf(stderr, "%02x ", buf2[i]); fprintf(stderr, "\n"); /* =========================== END SECTION ============================= */ /* ========================= START SECTION ============================= */ /* If using the the same key and iv over and over, stuff before this */ /* section and after this section needs to be done only ONCE */ memset(buf1, 0, sizeof(buf1)); memset(buf2, 0, sizeof(buf2)); /* Create cipher context */ HashContext = PK11_CreateContextBySymKey(hashMech, CKA_SIGN, SymKey, &SecParam); if (!HashContext) { fprintf(stderr, "no hash context today?\n"); goto out; } if (PK11_DigestBegin(HashContext) != SECSuccess) { fprintf(stderr, "hash doesn't begin?\n"); goto out; } rv1 = PK11_DigestOp(HashContext, (unsigned char *)data, 5); rv1 = PK11_DigestOp(HashContext, (unsigned char *)data+5, 4); rv2 = PK11_DigestFinal(HashContext, buf2, &tmp2_outlen, SHA1_BLOCK_LENGTH); PK11_DestroyContext(HashContext, PR_TRUE); if (rv1 != SECSuccess || rv2 != SECSuccess) goto out; fprintf(stderr, "Hash Data: "); for (i=0; i<tmp2_outlen; i++) fprintf(stderr, "%02x ", buf2[i]); fprintf(stderr, "\n"); /* =========================== END SECTION ============================= */ out: if (SymKey) PK11_FreeSymKey(SymKey); return 0; }
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; }
/* 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); } }
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; }
static int xmlSecNssDigestExecute(xmlSecTransformPtr transform, int last, xmlSecTransformCtxPtr transformCtx) { xmlSecNssDigestCtxPtr ctx; xmlSecBufferPtr in, out; SECStatus rv; int ret; xmlSecAssert2(xmlSecNssDigestCheckId(transform), -1); xmlSecAssert2((transform->operation == xmlSecTransformOperationSign) || (transform->operation == xmlSecTransformOperationVerify), -1); xmlSecAssert2(transformCtx != NULL, -1); xmlSecAssert2(xmlSecTransformCheckSize(transform, xmlSecNssDigestSize), -1); ctx = xmlSecNssDigestGetCtx(transform); xmlSecAssert2(ctx != NULL, -1); xmlSecAssert2(ctx->digestCtx != NULL, -1); in = &(transform->inBuf); out = &(transform->outBuf); if(transform->status == xmlSecTransformStatusNone) { rv = PK11_DigestBegin(ctx->digestCtx); if(rv != SECSuccess) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), "PK11_DigestBegin", XMLSEC_ERRORS_R_CRYPTO_FAILED, "error code=%d", PORT_GetError()); return(-1); } transform->status = xmlSecTransformStatusWorking; } if(transform->status == xmlSecTransformStatusWorking) { xmlSecSize inSize; inSize = xmlSecBufferGetSize(in); if(inSize > 0) { rv = PK11_DigestOp(ctx->digestCtx, xmlSecBufferGetData(in), inSize); if (rv != SECSuccess) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), "PK11_DigestOp", XMLSEC_ERRORS_R_CRYPTO_FAILED, "error code=%d", PORT_GetError()); return(-1); } ret = xmlSecBufferRemoveHead(in, inSize); if(ret < 0) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), "xmlSecBufferRemoveHead", XMLSEC_ERRORS_R_XMLSEC_FAILED, "size=%d", inSize); return(-1); } } if(last) { unsigned int dgstSize; rv = PK11_DigestFinal(ctx->digestCtx, ctx->dgst, &dgstSize, sizeof(ctx->dgst)); if(rv != SECSuccess) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), "PK11_DigestFinal", XMLSEC_ERRORS_R_CRYPTO_FAILED, "error code=%d", PORT_GetError()); return(-1); } xmlSecAssert2(dgstSize > 0, -1); ctx->dgstSize = XMLSEC_SIZE_BAD_CAST(dgstSize); if(transform->operation == xmlSecTransformOperationSign) { ret = xmlSecBufferAppend(out, ctx->dgst, ctx->dgstSize); if(ret < 0) { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), "xmlSecBufferAppend", XMLSEC_ERRORS_R_XMLSEC_FAILED, "size=%d", ctx->dgstSize); return(-1); } } transform->status = xmlSecTransformStatusFinished; } } else if(transform->status == xmlSecTransformStatusFinished) { /* the only way we can get here is if there is no input */ xmlSecAssert2(xmlSecBufferGetSize(&(transform->inBuf)) == 0, -1); } else { xmlSecError(XMLSEC_ERRORS_HERE, xmlSecErrorsSafeString(xmlSecTransformGetName(transform)), NULL, XMLSEC_ERRORS_R_INVALID_STATUS, "status=%d", transform->status); return(-1); } return(0); }
PK11SymKey *PK11_Derive_lsw(PK11SymKey *base, CK_MECHANISM_TYPE mechanism, SECItem *param, CK_MECHANISM_TYPE target, CK_ATTRIBUTE_TYPE operation, int keysize) { SECOidTag oid; PK11Context *ctx; unsigned char dkey[HMAC_BUFSIZE * 2]; SECItem dkey_param; SECStatus status; unsigned int len = 0; CK_EXTRACT_PARAMS bs; chunk_t dkey_chunk; if ( (param == NULL) && (keysize == 0)) { switch (mechanism) { case CKM_SHA256_KEY_DERIVATION: oid = SEC_OID_SHA256; break; case CKM_SHA384_KEY_DERIVATION: oid = SEC_OID_SHA384; break; case CKM_SHA512_KEY_DERIVATION: oid = SEC_OID_SHA512; break; default: return PK11_Derive(base, mechanism, param, target, operation, keysize); } ctx = PK11_CreateDigestContext(oid); PR_ASSERT(ctx != NULL); status = PK11_DigestBegin(ctx); PR_ASSERT(status == SECSuccess); status = PK11_DigestKey(ctx, base); PR_ASSERT(status == SECSuccess); PK11_DigestFinal(ctx, dkey, &len, sizeof dkey); PK11_DestroyContext(ctx, PR_TRUE); dkey_chunk.ptr = dkey; dkey_chunk.len = len; PK11SymKey *tkey1 = pk11_derive_wrapper_lsw(base, CKM_CONCATENATE_DATA_AND_BASE, dkey_chunk, CKM_EXTRACT_KEY_FROM_KEY, CKA_DERIVE, 0); PR_ASSERT(tkey1 != NULL); bs = 0; dkey_param.data = (unsigned char*)&bs; dkey_param.len = sizeof(bs); PK11SymKey *tkey2 = PK11_Derive(tkey1, CKM_EXTRACT_KEY_FROM_KEY, &dkey_param, target, operation, len); PR_ASSERT(tkey2 != NULL); if (tkey1 != NULL) PK11_FreeSymKey(tkey1); return tkey2; } else { return PK11_Derive(base, mechanism, param, target, operation, keysize); } }
int sss_password_decrypt(TALLOC_CTX *mem_ctx, char *b64encoded, char **password) { SECStatus sret; int ret; TALLOC_CTX *tmp_ctx = NULL; struct crypto_mech_data *mech_props; struct sss_nss_crypto_ctx *cctx; int plainlen; unsigned int digestlen; unsigned char *obfbuf = NULL; size_t obflen; char *pwdbuf; /* for unmarshaling data */ uint16_t meth; uint16_t ctsize; size_t p = 0; unsigned char *cryptotext; unsigned char *keybuf; unsigned char *ivbuf; unsigned char sentinel_check[OBF_BUFFER_SENTINEL_SIZE]; tmp_ctx = talloc_new(mem_ctx); if (!tmp_ctx) { return ENOMEM; } /* initialize NSS if needed */ ret = nspr_nss_init(); if (ret != EOK) { ret = EIO; goto done; } /* Base64 decode the incoming buffer */ obfbuf = sss_base64_decode(tmp_ctx, b64encoded, &obflen); if (!obfbuf) { ret = ENOMEM; goto done; } /* unpack obfuscation buffer */ SAFEALIGN_COPY_UINT16_CHECK(&meth, obfbuf+p, obflen, &p); DEBUG(SSSDBG_TRACE_INTERNAL, "Read method: %d\n", meth); SAFEALIGN_COPY_UINT16_CHECK(&ctsize, obfbuf+p, obflen, &p); DEBUG(SSSDBG_TRACE_INTERNAL, "Read bufsize: %d\n", ctsize); mech_props = get_crypto_mech_data(meth); if (mech_props == NULL) { ret = EINVAL; goto done; } /* check that we got sane mechanism properties and cryptotext size */ memcpy(sentinel_check, obfbuf + p + mech_props->keylen + mech_props->bsize + ctsize, OBF_BUFFER_SENTINEL_SIZE); if (memcmp(sentinel_check, OBF_BUFFER_SENTINEL, OBF_BUFFER_SENTINEL_SIZE) != 0) { DEBUG(SSSDBG_FATAL_FAILURE, "Obfuscation buffer seems corrupt, aborting\n"); ret = EFAULT; goto done; } /* copy out key, ivbuf and cryptotext */ keybuf = talloc_array(tmp_ctx, unsigned char, mech_props->keylen); if (keybuf == NULL) { ret = ENOMEM; goto done; } safealign_memcpy(keybuf, obfbuf+p, mech_props->keylen, &p); ivbuf = talloc_array(tmp_ctx, unsigned char, mech_props->bsize); if (ivbuf == NULL) { ret = ENOMEM; goto done; } safealign_memcpy(ivbuf, obfbuf+p, mech_props->bsize, &p); cryptotext = talloc_array(tmp_ctx, unsigned char, ctsize); if (cryptotext == NULL) { ret = ENOMEM; goto done; } safealign_memcpy(cryptotext, obfbuf+p, ctsize, &p); ret = nss_ctx_init(tmp_ctx, mech_props, &cctx); if (ret) { DEBUG(SSSDBG_CRIT_FAILURE, "Cannot initialize NSS context\n"); goto done; } cctx->iv = talloc_zero(cctx, SECItem); cctx->key = talloc_zero(cctx, SECItem); if (!cctx->iv || !cctx->key) { ret = ENOMEM; goto done; } MAKE_SECITEM(ivbuf, mech_props->bsize, cctx->iv); MAKE_SECITEM(keybuf, mech_props->keylen, cctx->key); ret = nss_encrypt_decrypt_init(mech_props, false, cctx); if (ret) { goto done; } pwdbuf = talloc_array(tmp_ctx, char, ctsize); if (!pwdbuf) { ret = ENOMEM; goto done; } sret = PK11_CipherOp(cctx->ectx, (unsigned char *) pwdbuf, &plainlen, ctsize, cryptotext, ctsize); if (sret != SECSuccess) { DEBUG(SSSDBG_CRIT_FAILURE, "Cannot execute the encryption operation (err %d)\n", PR_GetError()); ret = EIO; goto done; } sret = PK11_DigestFinal(cctx->ectx, (unsigned char *) pwdbuf+plainlen, &digestlen, ctsize - plainlen); if (sret != SECSuccess) { DEBUG(SSSDBG_CRIT_FAILURE, "Cannot execute the encryption operation (err %d)\n", PR_GetError()); ret = EIO; goto done; } *password = talloc_move(mem_ctx, &pwdbuf); ret = EOK; done: talloc_free(tmp_ctx); nspr_nss_cleanup(); return ret; }
int generate_digest(pesign_context *ctx, Pe *pe) { void *hash_base; size_t hash_size; struct pe32_opt_hdr *pe32opthdr = NULL; struct pe32plus_opt_hdr *pe64opthdr = NULL; PK11Context *pk11ctx; unsigned long hashed_bytes = 0; int rc = -1; if (!pe) { fprintf(stderr, "pesign: no output pe ready\n"); exit(1); } struct pe_hdr pehdr; if (pe_getpehdr(pe, &pehdr) == NULL) { fprintf(stderr, "pesign: invalid output file header\n"); exit(1); } void *map = NULL; size_t map_size = 0; /* 1. Load the image header into memory - should be done * 2. Initialize SHA hash context. */ map = pe_rawfile(pe, &map_size); if (!map) { fprintf(stderr, "pesign: could not get raw output file address\n"); exit(1); } pk11ctx = PK11_CreateDigestContext(ctx->cms_ctx.digest_oid_tag); if (!pk11ctx) { fprintf(stderr, "pesign: could not initialize digest\n"); exit(1); } PK11_DigestBegin(pk11ctx); /* 3. Calculate the distance from the base of the image header to the * image checksum. * 4. Hash the image header from start to the beginning of the * checksum. */ hash_base = map; switch (pe_kind(pe)) { case PE_K_PE_EXE: { void *opthdr = pe_getopthdr(pe); pe32opthdr = opthdr; hash_size = (uintptr_t)&pe32opthdr->csum - (uintptr_t)hash_base; break; } case PE_K_PE64_EXE: { void *opthdr = pe_getopthdr(pe); pe64opthdr = opthdr; hash_size = (uintptr_t)&pe64opthdr->csum - (uintptr_t)hash_base; break; } default: goto error; } PK11_DigestOp(pk11ctx, hash_base, hash_size); /* 5. Skip over the image checksum * 6. Get the address of the beginning of the cert dir entry * 7. Hash from the end of the csum to the start of the cert dirent. */ hash_base += hash_size; hash_base += pe32opthdr ? sizeof(pe32opthdr->csum) : sizeof(pe64opthdr->csum); data_directory *dd; rc = pe_getdatadir(pe, &dd); if (rc < 0 || !dd) goto error; hash_size = (uintptr_t)&dd->certs - (uintptr_t)hash_base; PK11_DigestOp(pk11ctx, hash_base, hash_size); /* 8. Skip over the crt dir * 9. Hash everything up to the end of the image header. */ hash_base = &dd->base_relocations; hash_size = (pe32opthdr ? pe32opthdr->header_size : pe64opthdr->header_size) - ((uintptr_t)&dd->base_relocations - (uintptr_t)map); PK11_DigestOp(pk11ctx, hash_base, hash_size); /* 10. Set SUM_OF_BYTES_HASHED to the size of the header. */ hashed_bytes = pe32opthdr ? pe32opthdr->header_size : pe64opthdr->header_size; struct section_header *shdrs = calloc(pehdr.sections, sizeof (*shdrs)); if (!shdrs) goto error; Pe_Scn *scn = NULL; for (int i = 0; i < pehdr.sections; i++) { scn = pe_nextscn(pe, scn); if (scn == NULL) break; pe_getshdr(scn, &shdrs[i]); } sort_shdrs(shdrs, pehdr.sections - 1); for (int i = 0; i < pehdr.sections; i++) { hash_base = (void *)((uintptr_t)map + shdrs[i].data_addr); hash_size = shdrs[i].raw_data_size; PK11_DigestOp(pk11ctx, hash_base, hash_size); hashed_bytes += hash_size; } if (map_size > hashed_bytes) { hash_base = (void *)((uintptr_t)map + hashed_bytes); hash_size = map_size - dd->certs.size - hashed_bytes; PK11_DigestOp(pk11ctx, hash_base, hash_size); } SECItem *digest = PORT_ArenaZAlloc(ctx->cms_ctx.arena, sizeof (SECItem)); if (!digest) goto error_shdrs; digest->type = siBuffer; digest->data = PORT_ArenaZAlloc(ctx->cms_ctx.arena, ctx->cms_ctx.digest_size); digest->len = ctx->cms_ctx.digest_size; if (!digest->data) goto error_digest; PK11_DigestFinal(pk11ctx, digest->data, &digest->len, ctx->cms_ctx.digest_size); ctx->cms_ctx.pe_digest = digest; if (shdrs) free(shdrs); PK11_DestroyContext(pk11ctx, PR_TRUE); return 0; error_digest: PORT_Free(digest->data); error_shdrs: if (shdrs) free(shdrs); error: PK11_DestroyContext(pk11ctx, PR_TRUE); fprintf(stderr, "pesign: could not digest file.\n"); exit(1); }
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, ¶ms); 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 */
int main (int argc, char *argv[]) { cpg_handle_t handle; cs_error_t result; int i = 0; int j; struct my_msg msg; struct iovec iov[2]; const char *options = "i:"; int iter = 1000; int opt; int run_forever = 1; unsigned int sha1_len; while ((opt = getopt(argc, argv, options)) != -1) { switch (opt) { case 'i': run_forever = 0; iter = atoi(optarg); break; } } result = cpg_initialize (&handle, &callbacks); if (result != CS_OK) { printf ("Couldn't initialize CPG service %d\n", result); exit (0); } if (NSS_NoDB_Init(".") != SECSuccess) { printf ("Couldn't initialize nss\n"); exit (0); } if ((sha1_context = PK11_CreateDigestContext(SEC_OID_SHA1)) == NULL) { printf ("Couldn't initialize nss\n"); exit (0); } result = cpg_join (handle, &group_name); if (result != CS_OK) { printf ("cpg_join failed with result %d\n", result); exit (1); } iov[0].iov_base = (void *)&msg; iov[0].iov_len = sizeof (struct my_msg); iov[1].iov_base = (void *)buffer; /* * Demonstrate cpg_mcast_joined */ i = 0; do { msg.msg_size = 100 + rand() % 100000; iov[1].iov_len = msg.msg_size; for (j = 0; j < msg.msg_size; j++) { buffer[j] = j; } sprintf ((char *)buffer, "cpg_mcast_joined: This is message %12d", i); PK11_DigestBegin(sha1_context); PK11_DigestOp(sha1_context, buffer, msg.msg_size); PK11_DigestFinal(sha1_context, msg.sha1, &sha1_len, sizeof(msg.sha1)); try_again_one: result = cpg_mcast_joined (handle, CPG_TYPE_AGREED, iov, 2); if (result == CS_ERR_TRY_AGAIN) { goto try_again_one; } result = cpg_dispatch (handle, CS_DISPATCH_ALL); i++; } while (run_forever || i < iter); PK11_DestroyContext(sha1_context, PR_TRUE); cpg_finalize (handle); return (0); }
static int calculate_nss_hash( knet_handle_t knet_h, const unsigned char *buf, const size_t buf_len, unsigned char *hash) { struct nsscrypto_instance *instance = knet_h->crypto_instance->model_instance; PK11Context* hash_context = NULL; SECItem hash_param; unsigned int hash_tmp_outlen = 0; int err = -1; /* Now do the digest */ hash_param.type = siBuffer; hash_param.data = 0; hash_param.len = 0; hash_context = PK11_CreateContextBySymKey(hash_to_nss[instance->crypto_hash_type], CKA_SIGN, instance->nss_sym_key_sign, &hash_param); if (!hash_context) { log_err(knet_h, KNET_SUB_NSSCRYPTO, "PK11_CreateContext failed (hash) hash_type=%d (err %d)", (int)hash_to_nss[instance->crypto_hash_type], PR_GetError()); goto out; } if (PK11_DigestBegin(hash_context) != SECSuccess) { log_err(knet_h, KNET_SUB_NSSCRYPTO, "PK11_DigestBegin failed (hash) hash_type=%d (err %d)", (int)hash_to_nss[instance->crypto_hash_type], PR_GetError()); goto out; } if (PK11_DigestOp(hash_context, buf, buf_len) != SECSuccess) { log_err(knet_h, KNET_SUB_NSSCRYPTO, "PK11_DigestOp failed (hash) hash_type=%d (err %d)", (int)hash_to_nss[instance->crypto_hash_type], PR_GetError()); goto out; } if (PK11_DigestFinal(hash_context, hash, &hash_tmp_outlen, hash_len[instance->crypto_hash_type]) != SECSuccess) { log_err(knet_h, KNET_SUB_NSSCRYPTO, "PK11_DigestFinale failed (hash) hash_type=%d (err %d)", (int)hash_to_nss[instance->crypto_hash_type], PR_GetError()); goto out; } err = 0; out: if (hash_context) { PK11_DestroyContext(hash_context, PR_TRUE); } return err; }
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; }
static void send_some_more_messages_zcb (void) { msg_t *my_msg; int i; int send_now; size_t payload_size; size_t total_size; unsigned int sha1_len; cs_error_t res; cpg_flow_control_state_t fc_state; void *zcb_buffer; if (cpg_fd < 0) return; send_now = my_msgs_to_send; payload_size = (rand() % 100000); total_size = payload_size + sizeof (msg_t); cpg_zcb_alloc (cpg_handle, total_size, &zcb_buffer); my_msg = (msg_t*)zcb_buffer; qb_log(LOG_DEBUG, "send_now:%d", send_now); my_msg->pid = my_pid; my_msg->nodeid = my_nodeid; my_msg->size = sizeof (msg_t) + payload_size; my_msg->seq = my_msgs_sent; for (i = 0; i < payload_size; i++) { my_msg->payload[i] = i; } PK11_DigestBegin(sha1_context); PK11_DigestOp(sha1_context, my_msg->payload, payload_size); PK11_DigestFinal(sha1_context, my_msg->sha1, &sha1_len, sizeof(my_msg->sha1)); for (i = 0; i < send_now; i++) { res = cpg_flow_control_state_get (cpg_handle, &fc_state); if (res == CS_OK && fc_state == CPG_FLOW_CONTROL_ENABLED) { /* lets do this later */ send_some_more_messages_later (); qb_log (LOG_INFO, "flow control enabled."); goto free_buffer; } res = cpg_zcb_mcast_joined (cpg_handle, CPG_TYPE_AGREED, zcb_buffer, total_size); if (res == CS_ERR_TRY_AGAIN) { /* lets do this later */ send_some_more_messages_later (); goto free_buffer; } else if (res != CS_OK) { qb_log (LOG_ERR, "cpg_mcast_joined error:%d, exiting.", res); exit (-2); } my_msgs_sent++; my_msgs_to_send--; } free_buffer: cpg_zcb_free (cpg_handle, zcb_buffer); }
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; }
static void send_some_more_messages_normal (void) { msg_t my_msg; struct iovec iov[2]; int i; int send_now; size_t payload_size; cs_error_t res; cpg_flow_control_state_t fc_state; int retries = 0; time_t before; unsigned int sha1_len; if (cpg_fd < 0) return; send_now = my_msgs_to_send; qb_log (LOG_TRACE, "send_now:%d", send_now); my_msg.pid = my_pid; my_msg.nodeid = my_nodeid; payload_size = (rand() % 10000); my_msg.size = sizeof (msg_t) + payload_size; my_msg.seq = my_msgs_sent; for (i = 0; i < payload_size; i++) { buffer[i] = i; } PK11_DigestBegin(sha1_context); PK11_DigestOp(sha1_context, buffer, payload_size); PK11_DigestFinal(sha1_context, my_msg.sha1, &sha1_len, sizeof(my_msg.sha1)); iov[0].iov_len = sizeof (msg_t); iov[0].iov_base = &my_msg; iov[1].iov_len = payload_size; iov[1].iov_base = buffer; for (i = 0; i < send_now; i++) { if (in_cnchg && pcmk_test) { retries = 0; before = time(NULL); cs_repeat(retries, 30, res = cpg_mcast_joined(cpg_handle, CPG_TYPE_AGREED, iov, 2)); if (retries > 20) { qb_log (LOG_ERR, "cs_repeat: blocked for :%lu secs.", (unsigned long)(time(NULL) - before)); } if (res != CS_OK) { qb_log (LOG_ERR, "cpg_mcast_joined error:%d.", res); return; } } else { res = cpg_flow_control_state_get (cpg_handle, &fc_state); if (res == CS_OK && fc_state == CPG_FLOW_CONTROL_ENABLED) { /* lets do this later */ send_some_more_messages_later (); qb_log (LOG_INFO, "flow control enabled."); return; } res = cpg_mcast_joined (cpg_handle, CPG_TYPE_AGREED, iov, 2); if (res == CS_ERR_TRY_AGAIN) { /* lets do this later */ send_some_more_messages_later (); if (i > 0) { qb_log (LOG_INFO, "TRY_AGAIN %d to send.", my_msgs_to_send); } return; } else if (res != CS_OK) { qb_log (LOG_ERR, "cpg_mcast_joined error:%d, exiting.", res); exit (-2); } } my_msgs_sent++; my_msg.seq = my_msgs_sent; my_msgs_to_send--; } qb_log (LOG_TRACE, "sent %d; to send %d.", my_msgs_sent, my_msgs_to_send); }
int sss_password_encrypt(TALLOC_CTX *mem_ctx, const char *password, int plen, enum obfmethod meth, char **obfpwd) { SECStatus sret; int ret; TALLOC_CTX *tmp_ctx = NULL; struct crypto_mech_data *mech_props; struct sss_nss_crypto_ctx *cctx; unsigned char *plaintext; unsigned char *cryptotext; int ct_maxsize; int ctlen; unsigned int digestlen; int result_len; unsigned char *obfbuf; size_t obufsize = 0; size_t p = 0; tmp_ctx = talloc_new(mem_ctx); if (!tmp_ctx) { return ENOMEM; } /* initialize NSS if needed */ ret = nspr_nss_init(); if (ret != EOK) { ret = EIO; goto done; } mech_props = get_crypto_mech_data(meth); if (mech_props == NULL) { ret = EINVAL; goto done; } ret = nss_ctx_init(tmp_ctx, mech_props, &cctx); if (ret) { DEBUG(SSSDBG_CRIT_FAILURE, "Cannot initialize NSS context\n"); goto done; } /* generate random encryption and IV key */ ret = generate_random_key(cctx, cctx->slot, mech_props, &cctx->key); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "Could not generate encryption key\n"); goto done; } ret = generate_random_key(cctx, cctx->slot, mech_props, &cctx->iv); if (ret != EOK) { DEBUG(SSSDBG_CRIT_FAILURE, "Could not generate initialization vector\n"); goto done; } ret = nss_encrypt_decrypt_init(mech_props, true, cctx); if (ret) { DEBUG(SSSDBG_CRIT_FAILURE, "Cannot initialize NSS context properties\n"); goto done; } plaintext = (unsigned char *) talloc_strndup(tmp_ctx, password, plen); if (!plaintext) { ret = ENOMEM; goto done; } /* cryptotext buffer must be at least len(plaintext)+blocksize */ ct_maxsize = plen + (mech_props->bsize); cryptotext = talloc_array(tmp_ctx, unsigned char, ct_maxsize); if (!cryptotext) { ret = ENOMEM; goto done; } /* sample data we'll encrypt and decrypt */ sret = PK11_CipherOp(cctx->ectx, cryptotext, &ctlen, ct_maxsize, plaintext, plen); if (sret != SECSuccess) { DEBUG(SSSDBG_CRIT_FAILURE, "Cannot execute the encryption operation (err %d)\n", PR_GetError()); ret = EIO; goto done; } sret = PK11_DigestFinal(cctx->ectx, cryptotext+ctlen, &digestlen, ct_maxsize-ctlen); if (sret != SECSuccess) { DEBUG(SSSDBG_CRIT_FAILURE, "Cannot execute the digest operation (err %d)\n", PR_GetError()); ret = EIO; goto done; } result_len = ctlen + digestlen; if (result_len < 0 || result_len > UINT16_MAX) { ret = ERANGE; goto done; } /* Pack the obfuscation buffer */ /* The buffer consists of: * uint16_t the type of the cipher * uint16_t length of the cryptotext in bytes (clen) * uint8_t[klen] key * uint8_t[blen] IV * uint8_t[clen] cryptotext * 4 bytes of "sentinel" denoting end of the buffer */ obufsize = sizeof(uint16_t) + sizeof(uint16_t) + mech_props->keylen + mech_props->bsize + result_len + OBF_BUFFER_SENTINEL_SIZE; obfbuf = talloc_array(tmp_ctx, unsigned char, obufsize); if (!obfbuf) { ret = ENOMEM; goto done; } DEBUG(SSSDBG_TRACE_INTERNAL, "Writing method: %d\n", meth); SAFEALIGN_SET_UINT16(&obfbuf[p], meth, &p); DEBUG(SSSDBG_TRACE_INTERNAL, "Writing bufsize: %d\n", result_len); SAFEALIGN_SET_UINT16(&obfbuf[p], result_len, &p); safealign_memcpy(&obfbuf[p], cctx->key->data, mech_props->keylen, &p); safealign_memcpy(&obfbuf[p], cctx->iv->data, mech_props->bsize, &p); safealign_memcpy(&obfbuf[p], cryptotext, result_len, &p); safealign_memcpy(&obfbuf[p], OBF_BUFFER_SENTINEL, OBF_BUFFER_SENTINEL_SIZE, &p); /* Base64 encode the resulting buffer */ *obfpwd = sss_base64_encode(mem_ctx, obfbuf, obufsize); if (*obfpwd == NULL) { ret = ENOMEM; goto done; } ret = EOK; done: talloc_free(tmp_ctx); nspr_nss_cleanup(); return ret; }