static PARCBuffer * _encodeControlPlaneInformation(const CCNxControl *cpiControlMessage) { PARCJSON *json = ccnxControl_GetJson(cpiControlMessage); char *str = parcJSON_ToCompactString(json); // include +1 because we need the NULL byte size_t len = strlen(str) + 1; size_t packetLength = sizeof(_MetisTlvFixedHeaderV0) + sizeof(MetisTlvType) + len; PARCBuffer *packet = parcBuffer_Allocate(packetLength); _MetisTlvFixedHeaderV0 hdr; memset(&hdr, 0, sizeof(hdr)); hdr.version = 0; hdr.packetType = METIS_PACKET_TYPE_CONTROL; hdr.payloadLength = htons(len + sizeof(MetisTlvType)); parcBuffer_PutArray(packet, sizeof(hdr), (uint8_t *) &hdr); MetisTlvType tlv = { .type = htons(T_CPI), .length = htons(len) }; parcBuffer_PutArray(packet, sizeof(tlv), (uint8_t *) &tlv); parcBuffer_PutArray(packet, len, (uint8_t *) str); parcMemory_Deallocate((void **) &str); return parcBuffer_Flip(packet); }
/** * If the user specified a device name, set the MAC address in ether->macAddress * * <#Paragraphs Of Explanation#> * * @param [in] ether An allocated MetisGenericEther * @param [in] devstr A C-String of the device name * * Example: * @code * <#example#> * @endcode */ static void _darwinEthernet_SetInterfaceAddress(MetisGenericEther *ether, const char *devstr) { if (devstr) { struct ifaddrs *ifaddr; int failure = getifaddrs(&ifaddr); assertFalse(failure, "Error getifaddrs: (%d) %s", errno, strerror(errno)); struct ifaddrs *next; for (next = ifaddr; next != NULL; next = next->ifa_next) { if (strcmp(next->ifa_name, devstr) == 0) { if (next->ifa_addr->sa_family == AF_LINK) { struct sockaddr_dl *addr_dl = (struct sockaddr_dl *) next->ifa_addr; // addr_dl->sdl_data[12] contains the interface name followed by the MAC address, so // need to offset in to the array past the interface name. PARCBuffer *addr = parcBuffer_Allocate(addr_dl->sdl_alen); parcBuffer_PutArray(addr, addr_dl->sdl_alen, (uint8_t *) &addr_dl->sdl_data[ addr_dl->sdl_nlen]); parcBuffer_Flip(addr); ether->macAddress = addr; // break out of loop and freeifaddrs break; } } } freeifaddrs(ifaddr); } }
LONGBOW_TEST_CASE(Object, parcRandomAccessFile_Write) { char *fname = "tmpfile"; PARCFile *file = parcFile_Create(fname); parcFile_CreateNewFile(file); uint8_t data[128]; for (int i = 0; i < 128; i++) { data[i] = i; } PARCRandomAccessFile *instance = parcRandomAccessFile_Open(file); PARCBuffer *buffer = parcBuffer_Allocate(128); parcBuffer_PutArray(buffer, 128, data); parcBuffer_Flip(buffer); size_t numBytes = parcRandomAccessFile_Write(instance, buffer); assertTrue(numBytes == 128, "Expected 128 bytes to be read, but got %zu", numBytes); parcBuffer_Release(&buffer); parcRandomAccessFile_Close(instance); parcRandomAccessFile_Release(&instance); uint8_t bytes[128]; FILE *fp = fopen(fname, "r"); numBytes = fread(bytes, 1, 128, fp); assertTrue(numBytes == 128, "Expected 128 bytes to be read, but got %zu", numBytes); fclose(fp); assertTrue(memcmp(data, bytes, 128) == 0, "Expected buffers to be equal"); parcFile_Release(&file); }
static PARCBuffer * _createDerivedKey(const char *key, size_t keylength, unsigned char *salt, unsigned int saltlen) { unsigned char buffer[SHA256_DIGEST_LENGTH]; HMAC(EVP_sha256(), key, (int) keylength, salt, saltlen, buffer, NULL); return parcBuffer_PutArray(parcBuffer_Allocate(SHA256_DIGEST_LENGTH), SHA256_DIGEST_LENGTH, buffer); }
LONGBOW_TEST_CASE(Global, parcSignature_Equals) { PARCBuffer *bits = parcBuffer_Allocate(10); // arbitrary bufer size -- not important PARCBuffer *otherBits = parcBuffer_Allocate(strlen("hello")); parcBuffer_PutArray(otherBits, strlen("hello"), (uint8_t *) "hello"); PARCSignature *x = parcSignature_Create(PARCSigningAlgorithm_DSA, PARC_HASH_SHA256, bits); PARCSignature *y = parcSignature_Create(PARCSigningAlgorithm_DSA, PARC_HASH_SHA256, bits); PARCSignature *z = parcSignature_Create(PARCSigningAlgorithm_DSA, PARC_HASH_SHA256, bits); PARCSignature *unequal1 = parcSignature_Create(PARCSigningAlgorithm_HMAC, PARC_HASH_SHA256, bits); PARCSignature *unequal2 = parcSignature_Create(PARCSigningAlgorithm_DSA, PARC_HASH_CRC32C, bits); PARCSignature *unequal3 = parcSignature_Create(PARCSigningAlgorithm_DSA, PARC_HASH_SHA256, otherBits); parcObjectTesting_AssertEqualsFunction(parcSignature_Equals, x, y, z, unequal1, unequal2, unequal3, NULL); parcSignature_Release(&x); parcSignature_Release(&y); parcSignature_Release(&z); parcSignature_Release(&unequal1); parcSignature_Release(&unequal2); parcSignature_Release(&unequal3); parcBuffer_Release(&bits); parcBuffer_Release(&otherBits); }
static PARCSignature * _SignDigest(PARCPublicKeySigner *signer, const PARCCryptoHash *digestToSign) { parcSecurity_AssertIsInitialized(); assertNotNull(signer, "Parameter must be non-null CCNxFileKeystore"); assertNotNull(digestToSign, "Buffer to sign must not be null"); // TODO: what is the best way to expose this? PARCKeyStore *keyStore = signer->keyStore; PARCBuffer *privateKeyBuffer = parcKeyStore_GetDEREncodedPrivateKey(keyStore); EVP_PKEY *privateKey = NULL; size_t keySize = parcBuffer_Remaining(privateKeyBuffer); uint8_t *bytes = parcBuffer_Overlay(privateKeyBuffer, keySize); privateKey = d2i_PrivateKey(EVP_PKEY_RSA, &privateKey, (const unsigned char **) &bytes, keySize); parcBuffer_Release(&privateKeyBuffer); RSA *rsa = EVP_PKEY_get1_RSA(privateKey); int opensslDigestType; switch (parcCryptoHash_GetDigestType(digestToSign)) { case PARCCryptoHashType_SHA256: opensslDigestType = NID_sha256; break; case PARCCryptoHashType_SHA512: opensslDigestType = NID_sha512; break; default: trapUnexpectedState("Unknown digest type: %s", parcCryptoHashType_ToString(parcCryptoHash_GetDigestType(digestToSign))); } uint8_t *sig = parcMemory_Allocate(RSA_size(rsa)); assertNotNull(sig, "parcMemory_Allocate(%u) returned NULL", RSA_size(rsa)); unsigned sigLength = 0; PARCBuffer *bb_digest = parcCryptoHash_GetDigest(digestToSign); int result = RSA_sign(opensslDigestType, (unsigned char *) parcByteArray_Array(parcBuffer_Array(bb_digest)), (int) parcBuffer_Remaining(bb_digest), sig, &sigLength, rsa); assertTrue(result == 1, "Got error from RSA_sign: %d", result); RSA_free(rsa); PARCBuffer *bbSign = parcBuffer_Allocate(sigLength); parcBuffer_Flip(parcBuffer_PutArray(bbSign, sigLength, sig)); parcMemory_Deallocate((void **) &sig); PARCSignature *signature = parcSignature_Create(_GetSigningAlgorithm(signer), parcCryptoHash_GetDigestType(digestToSign), bbSign ); parcBuffer_Release(&bbSign); return signature; }
/** * Create a symmetric (secret) key of the given bit length (e.g. 256) * * Example: * @code * <#example#> * @endcode */ PARCBuffer * parcSymmetricSignerFileStore_CreateKey(unsigned bits) { assertTrue((bits & 0x07) == 0, "bits must be a multiple of 8"); unsigned keylength = bits / 8; uint8_t buffer[keylength]; RAND_bytes(buffer, keylength); return parcBuffer_Flip(parcBuffer_PutArray(parcBuffer_Allocate(keylength), keylength, buffer)); }
static PARCCryptoHash * _GetPublickKeyDigest(PARCPkcs12KeyStore *keystore) { parcSecurity_AssertIsInitialized(); assertNotNull(keystore, "Parameter must be non-null PARCPkcs12KeyStore"); if (keystore->public_key_digest == NULL) { AUTHORITY_KEYID *akid = X509_get_ext_d2i(keystore->x509_cert, NID_authority_key_identifier, NULL, NULL); if (akid != NULL) { ASN1_OCTET_STRING *skid = X509_get_ext_d2i(keystore->x509_cert, NID_subject_key_identifier, NULL, NULL); if (skid != NULL) { keystore->public_key_digest = parcBuffer_PutArray(parcBuffer_Allocate(skid->length), skid->length, skid->data); parcBuffer_Flip(keystore->public_key_digest); ASN1_OCTET_STRING_free(skid); } AUTHORITY_KEYID_free(akid); } } // If we could not load the digest from the certificate, then calculate it from the public key. if (keystore->public_key_digest == NULL) { uint8_t digestBuffer[SHA256_DIGEST_LENGTH]; int result = ASN1_item_digest(ASN1_ITEM_rptr(X509_PUBKEY), EVP_sha256(), X509_get_X509_PUBKEY(keystore->x509_cert), digestBuffer, NULL); if (result != 1) { assertTrue(0, "Could not compute digest over certificate public key"); } else { keystore->public_key_digest = parcBuffer_PutArray(parcBuffer_Allocate(SHA256_DIGEST_LENGTH), SHA256_DIGEST_LENGTH, digestBuffer); parcBuffer_Flip(keystore->public_key_digest); } } // This stores a reference, so keystore->public_key_digest will remain valid // even if the cryptoHasher is destroyed return parcCryptoHash_Create(PARC_HASH_SHA256, keystore->public_key_digest); }
PARCBuffer * parcBuffer_CreateFromArray(const void *bytes, const size_t length) { assertTrue(length == 0 || bytes != NULL, "If the byte array is NULL, then length MUST be zero."); PARCBuffer *result = parcBuffer_Allocate(length); parcBuffer_PutArray(result, length, bytes); return result; }
CCNxNameSegment * ccnxNameSegment_CreateTypeValueArray(CCNxNameLabelType type, size_t length, const char array[length]) { PARCBuffer *value = parcBuffer_PutArray(parcBuffer_Allocate(length), length, (const uint8_t *) array); parcBuffer_Flip(value); CCNxNameSegment *result = ccnxNameSegment_CreateTypeValue(type, value); parcBuffer_Release(&value); return result; }
LONGBOW_TEST_CASE(Global, parcSignature_GetSignature) { PARCBuffer *expected = parcBuffer_Allocate(strlen("Hello")); parcBuffer_PutArray(expected, strlen("Hello"), (uint8_t *) "Hello"); PARCSignature *signature = parcSignature_Create(PARCSigningAlgorithm_DSA, PARC_HASH_SHA256, expected); PARCBuffer *actual = parcSignature_GetSignature(signature); assertTrue(parcBuffer_Equals(expected, actual), "Expected the original signature bits to be equal to the actual bits"); parcSignature_Release(&signature); parcBuffer_Release(&expected); }
PARCBuffer * parcBuffer_AllocateCString(const char *string) { size_t length = strlen(string); PARCBuffer *buffer = parcBuffer_Allocate(length + 1); parcBuffer_PutArray(buffer, length, (const uint8_t *) string); parcBuffer_PutUint8(buffer, 0); parcBuffer_SetPosition(buffer, buffer->position - 1); parcBuffer_Flip(buffer); return buffer; }
static PARCBuffer* _hmacFinalize(void *ctx) { uint8_t buffer[EVP_MAX_MD_SIZE]; unsigned length; HMAC_Final(ctx, buffer, &length); PARCBuffer *output = parcBuffer_Allocate(length); parcBuffer_PutArray(output, length, buffer); return output; }
LONGBOW_TEST_CASE(Global, parcSignature_GetHashType) { PARCBuffer *bits = parcBuffer_Allocate(strlen("Hello")); parcBuffer_PutArray(bits, strlen("Hello"), (uint8_t *) "Hello"); PARCCryptoHashType expected = PARC_HASH_SHA256; PARCSignature *signature = parcSignature_Create(PARCSigningAlgorithm_DSA, expected, bits); parcBuffer_Release(&bits); PARCCryptoHashType actual = parcSignature_GetHashType(signature); assertTrue(expected == actual, "Expected %d, actual %d", expected, actual); parcSignature_Release(&signature); }
static CCNxTlvDictionary * createSignedContentObject(void) { CCNxName *name = ccnxName_CreateFromURI("lci:/some/name"); PARCBuffer *payload = parcBuffer_Flip(parcBuffer_PutArray(parcBuffer_Allocate(20), 11, (uint8_t *) "the payload")); CCNxTlvDictionary *contentObject = ccnxContentObject_CreateWithDataPayload(name, payload); parcBuffer_Release(&payload); ccnxName_Release(&name); PARCBuffer *keyid = parcBuffer_Flip(parcBuffer_PutArray(parcBuffer_Allocate(20), 5, (uint8_t *) "keyid")); ccnxValidationRsaSha256_Set(contentObject, keyid, NULL); parcBuffer_Release(&keyid); PARCBuffer *sigbits = parcBuffer_WrapCString("the signature"); PARCSignature *signature = parcSignature_Create(PARCSigningAlgorithm_RSA, PARC_HASH_SHA256, parcBuffer_Flip(sigbits)); ccnxContentObject_SetSignature(contentObject, keyid, signature, NULL); parcSignature_Release(&signature); parcBuffer_Release(&sigbits); return contentObject; }
LONGBOW_TEST_CASE(Global, parcSignature_GetSigningAlgorithm) { PARCBuffer *signatureBits = parcBuffer_Allocate(strlen("Hello")); parcBuffer_PutArray(signatureBits, strlen("Hello"), (uint8_t *) "Hello"); PARCSigningAlgorithm expected = PARCSigningAlgorithm_DSA; PARCSignature *signature = parcSignature_Create(expected, PARC_HASH_SHA256, signatureBits); PARCSigningAlgorithm actual = parcSignature_GetSigningAlgorithm(signature); assertTrue(expected == actual, "Expected %d, actual %d", expected, actual); parcSignature_Release(&signature); parcBuffer_Release(&signatureBits); }
PARCURISegment * parcURISegment_Create(size_t length, const unsigned char segment[length]) { PARCURISegment *result = NULL; PARCBuffer *buffer = parcBuffer_Allocate(length); if (buffer != NULL) { parcBuffer_PutArray(buffer, length, segment); parcBuffer_Flip(buffer); result = parcURISegment_CreateFromBuffer(buffer); parcBuffer_Release(&buffer); } return result; }
LONGBOW_TEST_CASE(Global, parcSignature_ToString) { PARCBuffer *signatureBits = parcBuffer_Allocate(strlen("Hello")); parcBuffer_PutArray(signatureBits, strlen("Hello"), (uint8_t *) "Hello"); PARCSigningAlgorithm expected = PARCSigningAlgorithm_DSA; PARCSignature *signature = parcSignature_Create(expected, PARC_HASH_SHA256, signatureBits); char *string = parcSignature_ToString(signature); assertNotNull(string, "Expected non-NULL result from parcSignature_ToString"); parcMemory_Deallocate((void **) &string); parcSignature_Release(&signature); parcBuffer_Release(&signatureBits); }
static PARCCryptoHash * _GetCertificateDigest(PARCPkcs12KeyStore *keystore) { parcSecurity_AssertIsInitialized(); assertNotNull(keystore, "Parameter must be non-null PARCPkcs12KeyStore"); if (keystore->certificate_digest == NULL) { uint8_t digestBuffer[SHA256_DIGEST_LENGTH]; int result = X509_digest(keystore->x509_cert, EVP_sha256(), digestBuffer, NULL); if (result) { keystore->certificate_digest = parcBuffer_Flip(parcBuffer_PutArray(parcBuffer_Allocate(SHA256_DIGEST_LENGTH), SHA256_DIGEST_LENGTH, digestBuffer)); } } PARCCryptoHash *hash = parcCryptoHash_Create(PARC_HASH_SHA256, keystore->certificate_digest); return hash; }
static PARCBuffer * _GetDEREncodedPrivateKey(PARCPkcs12KeyStore *keystore) { parcSecurity_AssertIsInitialized(); assertNotNull(keystore, "Parameter must be non-null PARCPkcs12KeyStore"); if (keystore->private_key_der == NULL) { uint8_t *der = NULL; // this allocates memory for der int derLength = i2d_PrivateKey(keystore->private_key, &der); if (derLength > 0) { keystore->private_key_der = parcBuffer_Flip(parcBuffer_PutArray(parcBuffer_Allocate(derLength), derLength, der)); } OPENSSL_free(der); } return parcBuffer_Copy(keystore->private_key_der); }
static PARCBuffer * _iovecToParcBuffer(const CCNxCodecNetworkBufferIoVec *iovec) { PARCBuffer *result = NULL; size_t iovcnt = ccnxCodecNetworkBufferIoVec_GetCount((CCNxCodecNetworkBufferIoVec *) iovec); const struct iovec *array = ccnxCodecNetworkBufferIoVec_GetArray((CCNxCodecNetworkBufferIoVec *) iovec); size_t totalbytes = 0; for (int i = 0; i < iovcnt; i++) { totalbytes += array[i].iov_len; } result = parcBuffer_Allocate(totalbytes); for (int i = 0; i < iovcnt; i++) { parcBuffer_PutArray(result, array[i].iov_len, array[i].iov_base); } parcBuffer_Flip(result); return result; }
PARCBuffer * athenaTransportLinkModule_CreateMessageBuffer(CCNxMetaMessage *message) { PARCBuffer *buffer = ccnxWireFormatMessage_GetWireFormatBuffer(message); // If there is no PARCBuffer present, check for an IO vector and convert that into a contiguous buffer. if (buffer == NULL) { CCNxCodecNetworkBufferIoVec *iovec = ccnxWireFormatMessage_GetIoVec(message); if (iovec == NULL) { // if there's no iovec or buffer, encode the message and return the iovec athena_EncodeMessage(message); iovec = ccnxWireFormatMessage_GetIoVec(message); } assertNotNull(iovec, "Null io vector"); size_t iovcnt = ccnxCodecNetworkBufferIoVec_GetCount((CCNxCodecNetworkBufferIoVec *) iovec); const struct iovec *array = ccnxCodecNetworkBufferIoVec_GetArray((CCNxCodecNetworkBufferIoVec *) iovec); // If it's a single vector wrap it in a buffer to avoid a copy if (iovcnt == 1) { buffer = parcBuffer_Wrap(array[0].iov_base, array[0].iov_len, 0, array[0].iov_len); } else { size_t totalbytes = 0; for (int i = 0; i < iovcnt; i++) { totalbytes += array[i].iov_len; } buffer = parcBuffer_Allocate(totalbytes); for (int i = 0; i < iovcnt; i++) { parcBuffer_PutArray(buffer, array[i].iov_len, array[i].iov_base); } parcBuffer_Flip(buffer); } } else { buffer = parcBuffer_Acquire(buffer); } return buffer; }
PARCBuffer * bufferFromString(size_t length, const char string[length]) { return parcBuffer_Flip(parcBuffer_PutArray(parcBuffer_Allocate(length), length, (const uint8_t *) string)); }
PARCBuffer * parcBuffer_PutCString(PARCBuffer *buffer, const char *string) { return parcBuffer_PutArray(buffer, strlen(string) + 1, (const uint8_t *) string); }
static int _UDPSend(AthenaTransportLink *athenaTransportLink, CCNxMetaMessage *ccnxMetaMessage) { struct _UDPLinkData *linkData = athenaTransportLink_GetPrivateData(athenaTransportLink); if (ccnxTlvDictionary_GetSchemaVersion(ccnxMetaMessage) == CCNxTlvDictionary_SchemaVersion_V0) { parcLog_Debug(athenaTransportLink_GetLogger(athenaTransportLink), "sending deprecated version %d message\n", ccnxTlvDictionary_GetSchemaVersion(ccnxMetaMessage)); } // Get a wire format buffer and write it out. PARCBuffer *wireFormatBuffer = ccnxWireFormatMessage_GetWireFormatBuffer(ccnxMetaMessage); if (wireFormatBuffer == NULL) { CCNxCodecNetworkBufferIoVec *iovec = ccnxWireFormatMessage_GetIoVec(ccnxMetaMessage); assertNotNull(iovec, "Null io vector"); size_t iovcnt = ccnxCodecNetworkBufferIoVec_GetCount((CCNxCodecNetworkBufferIoVec *) iovec); const struct iovec *array = ccnxCodecNetworkBufferIoVec_GetArray((CCNxCodecNetworkBufferIoVec *) iovec); // If it's a single vector wrap it in a buffer to avoid a copy if (iovcnt == 1) { wireFormatBuffer = parcBuffer_Wrap(array[0].iov_base, array[0].iov_len, 0, array[0].iov_len); } else { size_t totalbytes = 0; for (int i = 0; i < iovcnt; i++) { totalbytes += array[i].iov_len; } wireFormatBuffer = parcBuffer_Allocate(totalbytes); for (int i = 0; i < iovcnt; i++) { parcBuffer_PutArray(wireFormatBuffer, array[i].iov_len, array[i].iov_base); } parcBuffer_Flip(wireFormatBuffer); } } else { wireFormatBuffer = parcBuffer_Acquire(wireFormatBuffer); } size_t length = parcBuffer_Limit(wireFormatBuffer); char *buffer = parcBuffer_Overlay(wireFormatBuffer, length); if (linkData->link.mtu) { if (length > linkData->link.mtu) { errno = EMSGSIZE; parcBuffer_Release(&wireFormatBuffer); return -1; } } parcLog_Debug(athenaTransportLink_GetLogger(athenaTransportLink), "sending message (size=%d)", length); ssize_t writeCount = 0; #ifdef LINUX_IGNORESIGPIPE writeCount = sendto(linkData->fd, buffer, length, MSG_NOSIGNAL, (struct sockaddr *) &linkData->link.peerAddress, linkData->link.peerAddressLength); #else writeCount = sendto(linkData->fd, buffer, length, 0, (struct sockaddr *) &linkData->link.peerAddress, linkData->link.peerAddressLength); #endif // on error close the link, else return to retry a zero write if (writeCount == -1) { if (errno == EPIPE) { athenaTransportLink_SetEvent(athenaTransportLink, AthenaTransportLinkEvent_Error); } parcLog_Error(athenaTransportLink_GetLogger(athenaTransportLink), "send error (%s)", strerror(errno)); parcBuffer_Release(&wireFormatBuffer); return -1; } // Short write if (writeCount != length) { linkData->_stats.receive_ShortWrite++; parcLog_Debug(athenaTransportLink_GetLogger(athenaTransportLink), "short write"); parcBuffer_Release(&wireFormatBuffer); return -1; } parcBuffer_Release(&wireFormatBuffer); return 0; }