bool COSE_Encrypt_encrypt(HCOSE_ENCRYPT h, const byte * pbKey, size_t cbKey, cose_errback * perr) { int alg; const cn_cbor * cn_Alg = NULL; byte * pbAuthData = NULL; cn_cbor * pAuthData = NULL; cn_cbor * ptmp = NULL; size_t cbitKey; #ifdef USE_CBOR_CONTEXT cn_cbor_context * context = NULL; #endif COSE_Encrypt * pcose = (COSE_Encrypt *) h; CHECK_CONDITION(IsValidEncryptHandle(h), COSE_ERR_INVALID_PARAMETER); #ifdef USE_CBOR_CONTEXT context = &pcose->m_message.m_allocContext; #endif // USE_CBOR_CONTEXT cn_Alg = _COSE_map_get_int(&pcose->m_message, COSE_Header_Algorithm, COSE_BOTH, perr); if (cn_Alg == NULL) goto errorReturn; CHECK_CONDITION((cn_Alg->type == CN_CBOR_UINT) || (cn_Alg->type == CN_CBOR_INT), COSE_ERR_INVALID_PARAMETER); alg = (int) cn_Alg->v.uint; // Get the key size switch (alg) { #ifdef INCLUDE_AES_CCM case COSE_Algorithm_AES_CCM_64_64_128: case COSE_Algorithm_AES_CCM_16_128_128: case COSE_Algorithm_AES_CCM_64_128_128: case COSE_Algorithm_AES_CCM_16_64_128: cbitKey = 128; break; case COSE_Algorithm_AES_CCM_64_64_256: case COSE_Algorithm_AES_CCM_16_128_256: case COSE_Algorithm_AES_CCM_64_128_256: case COSE_Algorithm_AES_CCM_16_64_256: cbitKey = 256; break; #endif // INCLUDE_AES_CCM case COSE_Algorithm_AES_GCM_128: cbitKey = 128; break; case COSE_Algorithm_AES_GCM_192: cbitKey = 192; break; case COSE_Algorithm_AES_GCM_256: cbitKey = 256; break; default: FAIL_CONDITION(COSE_ERR_INVALID_PARAMETER); } // Build protected headers const cn_cbor * cbProtected = _COSE_encode_protected(&pcose->m_message, perr); if (cbProtected == NULL) goto errorReturn; // Build authenticated data size_t cbAuthData = 0; if (!_COSE_Encrypt_Build_AAD(&pcose->m_message, &pbAuthData, &cbAuthData, "Encrypted", perr)) goto errorReturn; switch (alg) { #ifdef INCLUDE_AES_CCM case COSE_Algorithm_AES_CCM_16_64_128: case COSE_Algorithm_AES_CCM_16_64_256: if (!AES_CCM_Encrypt((COSE_Enveloped *)pcose, 64, 16, pbKey, cbKey, pbAuthData, cbAuthData, perr)) goto errorReturn; break; case COSE_Algorithm_AES_CCM_16_128_128: case COSE_Algorithm_AES_CCM_16_128_256: if (!AES_CCM_Encrypt((COSE_Enveloped *)pcose, 128, 16, pbKey, cbKey, pbAuthData, cbAuthData, perr)) goto errorReturn; break; case COSE_Algorithm_AES_CCM_64_64_128: case COSE_Algorithm_AES_CCM_64_64_256: if (!AES_CCM_Encrypt((COSE_Enveloped *)pcose, 64, 64, pbKey, cbKey, pbAuthData, cbAuthData, perr)) goto errorReturn; break; case COSE_Algorithm_AES_CCM_64_128_128: case COSE_Algorithm_AES_CCM_64_128_256: if (!AES_CCM_Encrypt((COSE_Enveloped *)pcose, 128, 64, pbKey, cbKey, pbAuthData, cbAuthData, perr)) goto errorReturn; break; #endif case COSE_Algorithm_AES_GCM_128: case COSE_Algorithm_AES_GCM_192: case COSE_Algorithm_AES_GCM_256: if (!AES_GCM_Encrypt((COSE_Enveloped *)pcose, pbKey, cbKey, pbAuthData, cbAuthData, perr)) goto errorReturn; break; default: FAIL_CONDITION(COSE_ERR_INVALID_PARAMETER); } // Figure out the clean up if (pbAuthData != NULL) COSE_FREE(pbAuthData, context); if (pAuthData != NULL) cn_cbor_free(pAuthData CBOR_CONTEXT_PARAM); return true; errorReturn: if (pbAuthData != NULL) COSE_FREE(pbAuthData, context); if (pAuthData != NULL) cn_cbor_free(pAuthData CBOR_CONTEXT_PARAM); if (ptmp != NULL) cn_cbor_free(ptmp CBOR_CONTEXT_PARAM); return false; }
bool _COSE_Enveloped_encrypt(COSE_Enveloped * pcose, const byte * pbKeyIn, size_t cbKeyIn, const char * szContext, cose_errback * perr) { int alg; int t; COSE_RecipientInfo * pri; const cn_cbor * cn_Alg = NULL; byte * pbAuthData = NULL; size_t cbitKey; #ifdef USE_CBOR_CONTEXT cn_cbor_context * context = &pcose->m_message.m_allocContext; #endif bool fRet = false; byte * pbKey = NULL; size_t cbKey = 0; cn_Alg = _COSE_map_get_int(&pcose->m_message, COSE_Header_Algorithm, COSE_BOTH, perr); if (cn_Alg == NULL) goto errorReturn; CHECK_CONDITION((cn_Alg->type != CN_CBOR_TEXT), COSE_ERR_UNKNOWN_ALGORITHM); CHECK_CONDITION((cn_Alg->type == CN_CBOR_UINT) || (cn_Alg->type == CN_CBOR_INT), COSE_ERR_INVALID_PARAMETER); alg = (int) cn_Alg->v.uint; // Get the key size switch (alg) { #ifdef USE_AES_CCM_64_64_128 case COSE_Algorithm_AES_CCM_64_64_128: cbitKey = 128; break; #endif #ifdef USE_AES_CCM_16_128_128 case COSE_Algorithm_AES_CCM_16_128_128: cbitKey = 128; break; #endif #ifdef USE_AES_CCM_64_128_128 case COSE_Algorithm_AES_CCM_64_128_128: cbitKey = 128; break; #endif #ifdef USE_AES_CCM_16_64_128 case COSE_Algorithm_AES_CCM_16_64_128: cbitKey = 128; break; #endif #ifdef USE_AES_CCM_64_64_256 case COSE_Algorithm_AES_CCM_64_64_256: cbitKey = 256; break; #endif #ifdef USE_AES_CCM_16_128_256 case COSE_Algorithm_AES_CCM_16_128_256: cbitKey = 256; break; #endif #ifdef USE_AES_CCM_64_128_256 case COSE_Algorithm_AES_CCM_64_128_256: cbitKey = 256; break; #endif #ifdef USE_AES_CCM_16_64_256 case COSE_Algorithm_AES_CCM_16_64_256: cbitKey = 256; break; #endif #ifdef USE_AES_GCM_128 case COSE_Algorithm_AES_GCM_128: cbitKey = 128; break; #endif #ifdef USE_AES_GCM_192 case COSE_Algorithm_AES_GCM_192: cbitKey = 192; break; #endif #ifdef USE_AES_GCM_256 case COSE_Algorithm_AES_GCM_256: cbitKey = 256; break; #endif default: FAIL_CONDITION(COSE_ERR_UNKNOWN_ALGORITHM); } // Enveloped or Encrypted? if (pbKeyIn != NULL) { CHECK_CONDITION(cbKeyIn == cbitKey / 8, COSE_ERR_INVALID_PARAMETER); pbKey = pbKeyIn; cbKey = cbKeyIn; } else { // If we are doing direct encryption - then recipient generates the key t = 0; for (pri = pcose->m_recipientFirst; pri != NULL; pri = pri->m_recipientNext) { if (pri->m_encrypt.m_message.m_flags & 1) { CHECK_CONDITION(pbKey == NULL, COSE_ERR_INVALID_PARAMETER); t |= 1; pbKey = _COSE_RecipientInfo_generateKey(pri, alg, cbitKey, perr); cbKey = cbitKey / 8; if (pbKey == NULL) goto errorReturn; } else { t |= 2; } } CHECK_CONDITION(t != 3, COSE_ERR_INVALID_PARAMETER); if (t == 2) { pbKey = (byte *)COSE_CALLOC(cbitKey / 8, 1, context); CHECK_CONDITION(pbKey != NULL, COSE_ERR_OUT_OF_MEMORY); cbKey = cbitKey / 8; rand_bytes(pbKey, cbKey); } } // Build protected headers const cn_cbor * cbProtected = _COSE_encode_protected(&pcose->m_message, perr); if (cbProtected == NULL) goto errorReturn; #ifdef USE_COUNTER_SIGNATURES // Setup Counter Signatures if (!_COSE_CountSign_create(&pcose->m_message, NULL, CBOR_CONTEXT_PARAM_COMMA perr)) { goto errorReturn; } #endif // Build authenticated data size_t cbAuthData = 0; if (!_COSE_Encrypt_Build_AAD(&pcose->m_message, &pbAuthData, &cbAuthData, szContext, perr)) goto errorReturn; switch (alg) { #ifdef USE_AES_CCM_16_64_128 case COSE_Algorithm_AES_CCM_16_64_128: if (!AES_CCM_Encrypt(pcose, 64, 16, pbKey, cbKey, pbAuthData, cbAuthData, perr)) goto errorReturn; break; #endif #ifdef USE_AES_CCM_16_64_256 case COSE_Algorithm_AES_CCM_16_64_256: if (!AES_CCM_Encrypt(pcose, 64, 16, pbKey, cbKey, pbAuthData, cbAuthData, perr)) goto errorReturn; break; #endif #ifdef USE_AES_CCM_16_128_128 case COSE_Algorithm_AES_CCM_16_128_128: if (!AES_CCM_Encrypt(pcose, 128, 16, pbKey, cbKey, pbAuthData, cbAuthData, perr)) goto errorReturn; break; #endif #ifdef USE_AES_CCM_16_128_256 case COSE_Algorithm_AES_CCM_16_128_256: if (!AES_CCM_Encrypt(pcose, 128, 16, pbKey, cbKey, pbAuthData, cbAuthData, perr)) goto errorReturn; break; #endif #ifdef USE_AES_CCM_64_64_128 case COSE_Algorithm_AES_CCM_64_64_128: if (!AES_CCM_Encrypt(pcose, 64, 64, pbKey, cbKey, pbAuthData, cbAuthData, perr)) goto errorReturn; break; #endif #ifdef USE_AES_CCM_64_64_256 case COSE_Algorithm_AES_CCM_64_64_256: if (!AES_CCM_Encrypt(pcose, 64, 64, pbKey, cbKey, pbAuthData, cbAuthData, perr)) goto errorReturn; break; #endif #ifdef USE_AES_CCM_64_128_128 case COSE_Algorithm_AES_CCM_64_128_128: if (!AES_CCM_Encrypt(pcose, 128, 64, pbKey, cbKey, pbAuthData, cbAuthData, perr)) goto errorReturn; break; #endif #ifdef USE_AES_CCM_64_128_256 case COSE_Algorithm_AES_CCM_64_128_256: if (!AES_CCM_Encrypt(pcose, 128, 64, pbKey, cbKey, pbAuthData, cbAuthData, perr)) goto errorReturn; break; #endif #ifdef USE_AES_GCM_128 case COSE_Algorithm_AES_GCM_128: if (!AES_GCM_Encrypt(pcose, pbKey, cbKey, pbAuthData, cbAuthData, perr)) goto errorReturn; break; #endif #ifdef USE_AES_GCM_192 case COSE_Algorithm_AES_GCM_192: if (!AES_GCM_Encrypt(pcose, pbKey, cbKey, pbAuthData, cbAuthData, perr)) goto errorReturn; break; #endif #ifdef USE_AES_GCM_256 case COSE_Algorithm_AES_GCM_256: if (!AES_GCM_Encrypt(pcose, pbKey, cbKey, pbAuthData, cbAuthData, perr)) goto errorReturn; break; #endif default: FAIL_CONDITION(COSE_ERR_UNKNOWN_ALGORITHM); } for (pri = pcose->m_recipientFirst; pri != NULL; pri = pri->m_recipientNext) { if (!_COSE_Recipient_encrypt(pri, pbKey, cbKey, perr)) goto errorReturn; } // Figure out the clean up fRet = true; errorReturn: if (pbAuthData != NULL) COSE_FREE(pbAuthData, context); if ((pbKey != NULL) && (pbKey != pbKeyIn)) { memset(pbKey, 0, cbKey); COSE_FREE(pbKey, context); } return fRet; }