/// Return the 'Length' of the given LLDP T<b>L</b>V entry. /// The length is the low order bit from the zeroth byte /// plus all 8 bits of the second byte gsize get_lldptlv_len(const void* tlv_vp, ///<[in] Pointer to beginning of TLV entry const void* pktend) ///<[in] Pointer to one byte past end of packet { const unsigned char * tlvp = tlv_vp; guint8 byte0 = tlv_get_guint8(tlvp, pktend); guint8 byte1 = tlv_get_guint8(tlvp+1, pktend); return ((((gsize)(byte0&0x1)) << 8) & (gsize)0x1FF) | ((gsize)byte1) ; }
/// Given marshalled packet data corresponding to an CryptCurve25519 frame /// return the corresponding Frame /// In other words, un-marshall the data... /// In our case, this means we decrypt it in-place into many other frames... WINEXPORT Frame* cryptcurve25519_tlvconstructor(gpointer tlvstart, ///<[in/out] Start of marshalled CStringFrame data gconstpointer pktend, ///<[in] Pointer to first invalid byte past 'tlvstart' gpointer* ignorednewpkt, ///<[ignored] replacement packet gpointer* ignoredpktend) ///<[ignored] end of replacement packet { guint8* valptr = get_generic_tlv_nonconst_value(tlvstart, pktend); guint8* nonce; guint8* cyphertext; const guint8* tlvend8 = valptr + get_generic_tlv_len(tlvstart, pktend); guint8* plaintext; CryptCurve25519* ret; guint namelen; gsize cypherlength; // The first key name is in sender's key name // The second key name is in receiver's key name CryptFramePublicKey * sender_public_key = NULL; CryptFramePrivateKey* receiver_secret_key = NULL; const char* sender_pubkey_id = NULL; const char* rcvr_seckey_id = NULL; int j; (void)ignorednewpkt; (void)ignoredpktend; valptr = get_generic_tlv_nonconst_value(tlvstart, pktend); for (j=0; j < 2; ++j) { char * key_id; g_return_val_if_fail((gpointer)(valptr+2) <= pktend, NULL); namelen = tlv_get_guint8(valptr, pktend); valptr += 1; g_return_val_if_fail((gpointer)(valptr+namelen) <= pktend, NULL); key_id = (char *)valptr; g_return_val_if_fail (strnlen(key_id, namelen) == namelen -1, NULL); g_return_val_if_fail(_is_valid_curve25519_key_id(key_id , 0 == j ? PUBLICKEY : PRIVATEKEY), NULL); if (0 == j) { sender_public_key = cryptframe_public_key_by_id(key_id); sender_pubkey_id = key_id; }else{ receiver_secret_key = cryptframe_private_key_by_id(key_id); rcvr_seckey_id = key_id; } g_return_val_if_fail(key_id != NULL, NULL); valptr += namelen; } if (NULL == sender_public_key) { g_warning("%s.%d: No access to sender %s public key" , __FUNCTION__, __LINE__, sender_pubkey_id); return NULL; } if (NULL == receiver_secret_key) { g_warning("%s.%d: No access to receiver %s private key" , __FUNCTION__, __LINE__, rcvr_seckey_id); return NULL; } g_return_val_if_fail((gpointer)(valptr + (crypto_box_NONCEBYTES+crypto_box_MACBYTES)) <= pktend, NULL); nonce = valptr; cyphertext = nonce + crypto_box_NONCEBYTES; plaintext = cyphertext + crypto_box_MACBYTES; cypherlength = tlvend8 - cyphertext; DEBUGCKSUM4("nonce:", nonce, crypto_box_NONCEBYTES); DEBUGCKSUM4("sender public key :", sender_public_key -> public_key, crypto_box_PUBLICKEYBYTES); DEBUGCKSUM4("receiver private key:", receiver_secret_key->private_key, crypto_box_SECRETKEYBYTES); DEBUGMSG4("cypher offset versus tlvstart: %ld", (long)(cyphertext-(guint8*)tlvstart)); DEBUGCKSUM4("cypher text:", cyphertext, cypherlength); if (crypto_box_open_easy(plaintext, cyphertext, cypherlength, nonce , sender_public_key->public_key, receiver_secret_key->private_key) != 0) { g_warning("%s.%d: could not decrypt %d byte message encrypted with key pair [pub:%s, sec:%s]" , __FUNCTION__, __LINE__, (int)cypherlength, sender_pubkey_id, rcvr_seckey_id); return NULL; } DEBUGCKSUM4("plain text:", plaintext, cypherlength-crypto_box_MACBYTES); // Note that our return value's size will determine where the beginning of the // decrypted data is (according to it's dataspace() member function) ret = cryptcurve25519_new(get_generic_tlv_type(tlvstart, pktend) , (const char *)sender_pubkey_id , rcvr_seckey_id, FALSE, 0); return (ret ? &(ret->baseclass.baseclass) : NULL); }
/// @ref CryptCurve25519 'isvalid' member function (checks for valid cryptcurve25519 objects) FSTATIC gboolean _cryptcurve25519_default_isvalid(const Frame * fself, ///<[in] CryptCurve25519 object ('this') gconstpointer tlvstart, ///<[in] Pointer to the TLV for this CryptCurve25519 gconstpointer pktend) ///<[in] Pointer to one byte past the end of the packet { const CryptCurve25519* self = CASTTOCONSTCLASS(CryptCurve25519, fself); const guint8* valptr; const char* key_id; guint namelen; gsize pktlen; int j; // Validate "object" only if (NULL == tlvstart) { namelen = strnlen(self->baseclass.receiver_key_id, MAXCRYPTNAMELENGTH+1); if (fself->length != TLVLEN(self->baseclass.receiver_key_id, self->baseclass.sender_key_id)) { return FALSE; } namelen = strnlen(self->baseclass.receiver_key_id, MAXCRYPTNAMELENGTH+1); if (namelen >= MAXCRYPTNAMELENGTH || namelen < 1 ){ return FALSE; } if (!_is_valid_curve25519_key_id(self->baseclass.receiver_key_id, self->forsending? PUBLICKEY: PRIVATEKEY)) { return FALSE; } namelen = strnlen(self->baseclass.sender_key_id, MAXCRYPTNAMELENGTH+1); if (namelen >= MAXCRYPTNAMELENGTH || namelen < 1 ){ return FALSE; } if (!_is_valid_curve25519_key_id(self->baseclass.sender_key_id, self->forsending ? PRIVATEKEY: PUBLICKEY)) { return FALSE; } return TRUE; } // Validate TLV pktlen = get_generic_tlv_len(tlvstart, pktend); // 6 == two 1-byte lengths, and two NUL-terminated strings of at least 2 bytes each if (pktlen < (crypto_box_NONCEBYTES + crypto_box_MACBYTES+6)) { return FALSE; } valptr = get_generic_tlv_value(tlvstart, pktend); // Validate both key names in the packet... for (j=0; j < 2; ++ j) { if ((gconstpointer)(valptr+3) >= pktend) { return FALSE; } namelen = tlv_get_guint8(valptr, pktend); if (namelen < 2 || (namelen-1) > MAXCRYPTNAMELENGTH) { return FALSE; } valptr += 1; if ((gconstpointer)(valptr+namelen) > pktend) { return FALSE; } key_id = (const char *)(valptr); if (strnlen(key_id, namelen) != (namelen-1)) { return FALSE; } // We say PUBLICKEY since we don't know whether we're validating this // on the sender or the receiver end - and whether should be a public // or a private key will depend on which end we're at - and everyone // needs a public key. If we have a public key but need a private // key that will get caught when we try and decrypt it. // At least this catches garbage and unknown keys if (!_is_valid_curve25519_key_id(key_id, PUBLICKEY)) { g_warning("%s.%d: Packet encrypted using unknown key [%s]", __FUNCTION__, __LINE__ , key_id); return FALSE; } valptr += namelen; } return TRUE; }