/// Update packet data from the frame FSTATIC void _seqnoframe_updatedata(Frame* fself, ///< object whose data will be put into FrameSet packet gpointer tlvptr, ///< pointer to our current TLV entry gconstpointer pktend, ///< end of packet FrameSet* fs) ///< FrameSet that we're doing this for { SeqnoFrame* self = CASTTOCLASS(SeqnoFrame, fself); // NOTE - this gets rid of the "const" coming out of get_generic_tlv_value... ///@todo add a new get_generic_nonconst_tlv_value() function. guint8* pktpos = get_generic_tlv_nonconst_value(tlvptr, pktend); (void)fs; g_return_if_fail(NULL != pktpos); tlv_set_guint32(pktpos, self->_sessionid, pktend); tlv_set_guint64(pktpos+sizeof(guint32), self->_reqid, pktend); tlv_set_guint16(pktpos+sizeof(guint32)+sizeof(guint64),self->_qid, pktend); }
/// /// We update the data in the packet from our CryptCurve25519 object with the /// side-effect of encrypting all the frames already put into the packet. Note that /// this only works because we always construct the packet from the end back to the /// beginning. We do this in-place - fortunately the algorithms allow that... /// We effectively suck all the remaining frames into a single encrypted frame... FSTATIC void _cryptcurve25519_updatedata(Frame* f, ///< Frame to marshall gpointer tlvstart, ///< Start of our Frame in the packet gconstpointer pktend, ///< Last byte in the allocated packet FrameSet* unused_fs) ///< Pointer to our containing frameset { CryptCurve25519*self = CASTTOCLASS(CryptCurve25519, f); const guint8* pktend8 = pktend; //guint8* tlvstart8 = tlvstart; guint8* tlvval; guint8* valptr; guint32 plaintextoffset; guint32 plaintextsize; guint32 cyphertextoffset; guint32 nonceoffset; guint32 tlvsize; unsigned char* nonce; int j; (void)unused_fs; // [key1, key2, nonce, MAC, plaintext] DUMP3(__FUNCTION__, &f->baseclass, " is CryptCurve25519 Frame being processed."); DEBUGMSG3("%s.%d: tlvstart:%p, pktend:%p", __FUNCTION__, __LINE__, tlvstart, pktend); // The plain text starts immediately after our (incoming) frame plaintextoffset = f->length; // Plain text starts here cyphertextoffset = plaintextoffset - crypto_box_MACBYTES; // Preceded by MAC nonceoffset = cyphertextoffset - crypto_box_NONCEBYTES; // Preceded by nonce // Our (outgoing) frame consists of the original incoming frame plus all other frames after ours tlvval = get_generic_tlv_nonconst_value(tlvstart, pktend); tlvsize = pktend8 - tlvval; plaintextsize = (tlvsize - plaintextoffset); // Generate a "nonce" as part of the packet - make known plaintext attacks harder // ... lots of our plaintext is easy to figure out ... nonce = tlvval + nonceoffset; DEBUGMSG3("%s.%d: generating random nonce (%p, %d, %p)", __FUNCTION__, __LINE__ , nonce, (int)crypto_box_NONCEBYTES, nonce+crypto_box_NONCEBYTES); randombytes_buf(nonce, crypto_box_NONCEBYTES); DEBUGMSG3("%s.%d: random nonce generated.", __FUNCTION__, __LINE__); DEBUGMSG3("%s.%d: public->key_id: [%s], private_key->key_id: [%s]", __FUNCTION__, __LINE__ , self->public_key->key_id, self->private_key->key_id); DEBUGMSG3("%s.%d: calling crypto_box_easy(%p,%p,%d,%p,%p,%p)", __FUNCTION__, __LINE__ , tlvval+cyphertextoffset, tlvval+plaintextoffset, plaintextsize , nonce, self->public_key->public_key, self->private_key->private_key); DEBUGCKSUM4("plain text cksum:", tlvval+plaintextoffset, plaintextsize); DEBUGCKSUM4("receiver public key cksum:",self->public_key -> public_key, crypto_box_PUBLICKEYBYTES); DEBUGCKSUM4("sender private key cksum:", self->private_key->private_key, crypto_box_SECRETKEYBYTES); DEBUGCKSUM4("nonce cksum:", nonce, crypto_box_NONCEBYTES); // Encrypt in-place [we previously allocated enough space for authentication info] crypto_box_easy(tlvval+cyphertextoffset, tlvval+plaintextoffset, plaintextsize , nonce, self->public_key->public_key, self->private_key->private_key); DEBUGMSG4("cypher offset versus tlvstart: %ld", (long)(tlvval+cyphertextoffset-(guint8*)tlvstart)); DEBUGCKSUM4("cypher text checksum:", tlvval+cyphertextoffset, plaintextsize+crypto_box_MACBYTES); set_generic_tlv_type(tlvstart, self->baseclass.baseclass.type, pktend); set_generic_tlv_len(tlvstart, tlvsize, pktend); // Put in the frame type, length, key name length, and key name for both keys // We're the sender - our [private] key name goes first, then the receiver's [public] key name valptr = get_generic_tlv_nonconst_value(tlvstart, pktend); for (j=0; j < 2; ++j) { char * key_id = (j == 0 ? self->baseclass.sender_key_id : self->baseclass.receiver_key_id); int keylen = strlen(key_id)+1; tlv_set_guint8(valptr, keylen, pktend); valptr += 1; g_strlcpy((char *)valptr, key_id, keylen); valptr += keylen; } DEBUGMSG3("%s.%d: returning after next assert (tlvval:%p, tlvsize%d, pktend:%p" , __FUNCTION__, __LINE__, tlvval, (int)tlvsize, pktend); g_assert((tlvval + tlvsize) == pktend); DEBUGMSG3("%s.%d: returning (assert passed).", __FUNCTION__, __LINE__); }
/// 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); }