HRESULT Library_security_pkcs11_native_Microsoft_SPOT_Cryptoki_CryptokiDigest::DigestFinalInternal___SZARRAY_U1( CLR_RT_StackFrame& stack ) { TINYCLR_HEADER(); CLR_RT_HeapBlock* pThis = stack.This(); CLR_RT_HeapBlock* pSession = pThis[Library_security_pkcs11_native_Microsoft_SPOT_Cryptoki_SessionContainer::FIELD__m_session].Dereference(); CLR_INT32 digestSize = pThis[Library_security_pkcs11_native_Microsoft_SPOT_Cryptoki_CryptokiDigest::FIELD__m_hashSize].NumericByRef().s4; CLR_INT32 hSession; //CLR_INT32 maxProcessingBytes; FAULT_ON_NULL(pSession); hSession = (CK_SESSION_HANDLE)pSession[Library_security_pkcs11_native_Microsoft_SPOT_Cryptoki_Session::FIELD__m_handle].NumericByRef().s4; if(hSession == CK_SESSION_HANDLE_INVALID) TINYCLR_SET_AND_LEAVE(CLR_E_OBJECT_DISPOSED); // TODO: add code for processing chunks at a time if size is too big //maxProcessingBytes = pSession[Library_security_pkcs11_native_Microsoft_SPOT_Cryptoki_Session::FIELD__m_maxProcessingBytes].NumericByRef().s4; TINYCLR_CHECK_HRESULT(CLR_RT_HeapBlock_Array::CreateInstance(stack.PushValue(), digestSize, g_CLR_RT_WellKnownTypes.m_UInt8)); CRYPTOKI_CHECK_RESULT(stack, C_DigestFinal(hSession, stack.TopValue().DereferenceArray()->GetFirstElement(), (CK_ULONG_PTR)&digestSize)); TINYCLR_NOCLEANUP(); }
void DigestTests::testDigestFinal() { CK_RV rv; CK_SESSION_HANDLE hSession = CK_INVALID_HANDLE; CK_MECHANISM mechanism = { CKM_SHA512, NULL_PTR, 0 }; CK_BYTE data[] = {"Text to digest"}; CK_ULONG digestLen; CK_BYTE_PTR digest; // Just make sure that we finalize any previous tests CRYPTOKI_F_PTR( C_Finalize(NULL_PTR) ); rv = CRYPTOKI_F_PTR( C_DigestFinal(hSession, NULL_PTR, &digestLen) ); CPPUNIT_ASSERT(rv == CKR_CRYPTOKI_NOT_INITIALIZED); rv = CRYPTOKI_F_PTR( C_Initialize(NULL_PTR) ); CPPUNIT_ASSERT(rv == CKR_OK); rv = CRYPTOKI_F_PTR( C_OpenSession(m_initializedTokenSlotID, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR, &hSession) ); CPPUNIT_ASSERT(rv == CKR_OK); rv = CRYPTOKI_F_PTR( C_DigestFinal(CK_INVALID_HANDLE, NULL_PTR, &digestLen) ); CPPUNIT_ASSERT(rv == CKR_SESSION_HANDLE_INVALID); rv = CRYPTOKI_F_PTR( C_DigestFinal(hSession, NULL_PTR, &digestLen) ); CPPUNIT_ASSERT(rv == CKR_OPERATION_NOT_INITIALIZED); rv = CRYPTOKI_F_PTR( C_DigestInit(hSession, &mechanism) ); CPPUNIT_ASSERT(rv == CKR_OK); rv = CRYPTOKI_F_PTR( C_DigestUpdate(hSession, data, sizeof(data)-1) ); CPPUNIT_ASSERT(rv == CKR_OK); rv = CRYPTOKI_F_PTR( C_DigestFinal(hSession, NULL_PTR, NULL_PTR) ); CPPUNIT_ASSERT(rv == CKR_ARGUMENTS_BAD); rv = CRYPTOKI_F_PTR( C_DigestFinal(hSession, NULL_PTR, &digestLen) ); CPPUNIT_ASSERT(rv == CKR_OK); digest = (CK_BYTE_PTR)malloc(digestLen); digestLen = 0; rv = CRYPTOKI_F_PTR( C_DigestFinal(hSession, digest, &digestLen) ); CPPUNIT_ASSERT(rv == CKR_BUFFER_TOO_SMALL); rv = CRYPTOKI_F_PTR( C_DigestFinal(hSession, digest, &digestLen) ); CPPUNIT_ASSERT(rv == CKR_OK); free(digest); rv = CRYPTOKI_F_PTR( C_DigestFinal(hSession, NULL_PTR, &digestLen) ); CPPUNIT_ASSERT(rv == CKR_OPERATION_NOT_INITIALIZED); }
krb5_error_code k5_ef_hash(krb5_context context, CK_MECHANISM *mechanism, unsigned int icount, krb5_const krb5_data *input, krb5_data *output) { CK_RV rv; int i; CK_ULONG outlen = output->length; if ((rv = C_DigestInit(krb_ctx_hSession(context), mechanism)) != CKR_OK) { KRB5_LOG(KRB5_ERR, "C_DigestInit failed in k5_ef_hash: " "rv = 0x%x.", rv); return (PKCS_ERR); } for (i = 0; i < icount; i++) { if ((rv = C_DigestUpdate(krb_ctx_hSession(context), (CK_BYTE_PTR)input[i].data, (CK_ULONG)input[i].length)) != CKR_OK) { KRB5_LOG(KRB5_ERR, "C_DigestUpdate failed in k5_ef_hash: " "rv = 0x%x", rv); return (PKCS_ERR); } } if ((rv = C_DigestFinal(krb_ctx_hSession(context), (CK_BYTE_PTR)output->data, &outlen)) != CKR_OK) { KRB5_LOG(KRB5_ERR, "C_DigestFinal failed in k5_ef_hash: " "rv = 0x%x", rv); return (PKCS_ERR); } /* Narrowing conversion OK because hashes are much smaller than 2^32 */ output->length = outlen; KRB5_LOG0(KRB5_INFO, "k5_ef_hash() end"); return (0); }
/*ARGSUSED*/ static krb5_error_code k5_md5des_hash(krb5_context context, krb5_const krb5_keyblock *key, krb5_keyusage usage, const krb5_data *ivec, const krb5_data *input, krb5_data *output) { krb5_error_code ret = 0; krb5_data data; unsigned char conf[CONFLENGTH]; krb5_keyblock xorkey; int i; CK_MECHANISM mechanism; CK_RV rv; CK_ULONG hashlen = MD5_CKSUM_LENGTH; if (key->length != 8) return(KRB5_BAD_KEYSIZE); if (ivec) return(KRB5_CRYPTO_INTERNAL); if (output->length != (CONFLENGTH+MD5_CKSUM_LENGTH)) return(KRB5_CRYPTO_INTERNAL); /* create the confouder */ data.length = CONFLENGTH; data.data = (char *) conf; if ((ret = krb5_c_random_make_octets(context, &data))) return(ret); xorkey.magic = key->magic; xorkey.enctype = key->enctype; xorkey.length = key->length; xorkey.contents = (krb5_octet *)malloc(key->length); if (xorkey.contents == NULL) return(KRB5_CRYPTO_INTERNAL); (void) memcpy(xorkey.contents, key->contents, xorkey.length); for (i=0; i<xorkey.length; i++) xorkey.contents[i] ^= 0xf0; if (!mit_des_check_key_parity(xorkey.contents)) { ret = KRB5DES_BAD_KEYPAR; goto cleanup; } if (mit_des_is_weak_key(xorkey.contents)) { ret = KRB5DES_WEAK_KEY; goto cleanup; } /* hash the confounder, then the input data */ mechanism.mechanism = CKM_MD5; mechanism.pParameter = NULL_PTR; mechanism.ulParameterLen = 0; if ((rv = C_DigestInit(krb_ctx_hSession(context), &mechanism)) != CKR_OK) { KRB5_LOG(KRB5_ERR, "C_DigestInit failed in k5_md5des_hash: " "rv = 0x%x.", rv); ret = PKCS_ERR; goto cleanup; } if ((rv = C_DigestUpdate(krb_ctx_hSession(context), (CK_BYTE_PTR)conf, (CK_ULONG)sizeof(conf))) != CKR_OK) { KRB5_LOG(KRB5_ERR, "C_DigestUpdate failed in k5_md5des_hash: " "rv = 0x%x", rv); ret = PKCS_ERR; goto cleanup; } if ((rv = C_DigestUpdate(krb_ctx_hSession(context), (CK_BYTE_PTR)input->data, (CK_ULONG)input->length)) != CKR_OK) { KRB5_LOG(KRB5_ERR, "C_DigestUpdate failed in k5_md5des_hash: " "rv = 0x%x", rv); return(PKCS_ERR); } if ((rv = C_DigestFinal(krb_ctx_hSession(context), (CK_BYTE_PTR)(output->data + CONFLENGTH), (CK_ULONG_PTR)&hashlen)) != CKR_OK) { KRB5_LOG(KRB5_ERR, "C_DigestFinal failed in k5_md5des_hash: " "rv = 0x%x", rv); ret = PKCS_ERR; goto cleanup; } /* construct the buffer to be encrypted */ (void) memcpy(output->data, conf, CONFLENGTH); /* encrypt it, in place. this has a return value, but it's always zero. */ ret = mit_des_cbc_encrypt(context, (krb5_pointer) output->data, (krb5_pointer) output->data, output->length, &xorkey, (unsigned char*) mit_des_zeroblock, 1); cleanup: free(xorkey.contents); return(ret); }
/*ARGSUSED*/ static krb5_error_code k5_md5des_verify(krb5_context context, krb5_const krb5_keyblock *key, krb5_keyusage usage, krb5_const krb5_data *ivec, krb5_const krb5_data *input, krb5_const krb5_data *hash, krb5_boolean *valid) { krb5_error_code ret = 0; unsigned char plaintext[CONFLENGTH+MD5_CKSUM_LENGTH]; unsigned char digest[MD5_CKSUM_LENGTH]; krb5_keyblock xorkey; int i; int compathash = 0; CK_MECHANISM mechanism; CK_RV rv; CK_ULONG hashlen = MD5_CKSUM_LENGTH; if (key->length != 8) return(KRB5_BAD_KEYSIZE); if (ivec) return(KRB5_CRYPTO_INTERNAL); if (hash->length != (CONFLENGTH + MD5_CKSUM_LENGTH)) { #ifdef KRB5_MD5DES_BETA5_COMPAT if (hash->length != MD5_CKSUM_LENGTH) return(KRB5_CRYPTO_INTERNAL); else compathash = 1; #else return(KRB5_CRYPTO_INTERNAL); #endif } /* create and the encryption key */ xorkey.magic = key->magic; xorkey.enctype = key->enctype; xorkey.length = key->length; xorkey.contents = (krb5_octet *)malloc(key->length); if (xorkey.contents == NULL) return(KRB5_CRYPTO_INTERNAL); (void) memcpy(xorkey.contents, key->contents, xorkey.length); if (!compathash) { for (i=0; i<xorkey.length; i++) xorkey.contents[i] ^= 0xf0; } if (!mit_des_check_key_parity(xorkey.contents)) { ret = KRB5DES_BAD_KEYPAR; goto cleanup; } if (mit_des_is_weak_key(xorkey.contents)) { ret = KRB5DES_WEAK_KEY; goto cleanup; } /* decrypt it. this has a return value, but it's always zero. */ if (!compathash) { ret = mit_des_cbc_encrypt(context, (krb5_pointer) hash->data, (krb5_pointer) plaintext, hash->length, &xorkey, (unsigned char*) mit_des_zeroblock, 0); } else { ret = mit_des_cbc_encrypt(context, (krb5_pointer) hash->data, (krb5_pointer) plaintext, hash->length, &xorkey, xorkey.contents, 0); } if (ret) goto cleanup; /* hash the confounder, then the input data */ mechanism.mechanism = CKM_MD5; mechanism.pParameter = NULL_PTR; mechanism.ulParameterLen = 0; if ((rv = C_DigestInit(krb_ctx_hSession(context), &mechanism)) != CKR_OK) { KRB5_LOG(KRB5_ERR, "C_DigestInit failed in k5_md5des_verify: " "rv = 0x%x.", rv); ret = PKCS_ERR; goto cleanup; } if (!compathash) { if ((rv = C_DigestUpdate(krb_ctx_hSession(context), (CK_BYTE_PTR)plaintext, (CK_ULONG)CONFLENGTH)) != CKR_OK) { KRB5_LOG(KRB5_ERR, "C_DigestUpdate failed in k5_md5des_verify: " "rv = 0x%x", rv); ret = PKCS_ERR; goto cleanup; } } if ((rv = C_DigestUpdate(krb_ctx_hSession(context), (CK_BYTE_PTR)input->data, (CK_ULONG)input->length)) != CKR_OK) { KRB5_LOG(KRB5_ERR, "C_DigestUpdate failed in k5_md5des_verify: " "rv = 0x%x", rv); ret = PKCS_ERR; goto cleanup; } if ((rv = C_DigestFinal(krb_ctx_hSession(context), (CK_BYTE_PTR)digest, (CK_ULONG_PTR)&hashlen)) != CKR_OK) { KRB5_LOG(KRB5_ERR, "C_DigestFinal failed in k5_md5des_verify: " "rv = 0x%x", rv); ret = PKCS_ERR; goto cleanup; } /* compare the decrypted hash to the computed one */ if (!compathash) { *valid = (memcmp(plaintext+CONFLENGTH, digest, sizeof(digest)) == 0); } else { *valid = (memcmp(plaintext, digest, sizeof(digest)) == 0); } (void) memset(plaintext, 0, sizeof(plaintext)); cleanup: free(xorkey.contents); return(ret); }