Ideas from libotr... should we have them?
Created by: claucece
There is some functionality in libotr that we might want to have:
- Convert Operations
There is a callback that is made immediately before a message is encrypted and immediately after a message is decrypted. This callback can tweak the plaintext message as needed. For example, this could allow an application to convert formatting on a message if this would normally be done on the plaintext by some other entity while the message is in transit.
Do we think is useful?
- Add prefix to resent messages
/* Return a string that will be prefixed to any resent message. If this
- function is not provided by the application then the default prefix,
- "[resent]", will be used.
- */ const char *(*resent_msg_prefix)(void *opdata, ConnContext *context);
These operations give the option of chosing an alternative to the English string "[resent]", when a message is resent.
/* When timer_control is called, turn off any existing periodic * timer. * * Additionally, if interval > 0, set a new periodic timer * to go off every interval seconds. When that timer fires, you * must call otrl_message_poll(userstate, uiops, uiopdata); from the * main libotr thread. * * The timing does not have to be exact; this timer is used to * provide forward secrecy by cleaning up stale private state that * may otherwise stick around in memory. Note that the * timer_control callback may be invoked from otrl_message_poll * itself, possibly to indicate that interval == 0 (that is, that * there's no more periodic work to be done at this time). * * If you set this callback to NULL, then you must ensure that your * application calls otrl_message_poll(userstate, uiops, uiopdata); * from the main libotr thread every definterval seconds (where * definterval can be obtained by calling * definterval = otrl_message_poll_get_default_interval(userstate); * right after creating the userstate). The advantage of * implementing the timer_control callback is that the timer can be * turned on by libotr only when it's needed. * * It is not a problem (except for a minor performance hit) to call * otrl_message_poll more often than requested, whether * timer_control is implemented or not. * * If you fail to implement the timer_control callback, and also * fail to periodically call otrl_message_poll, then you open your * users to a possible forward secrecy violation: an attacker that * compromises the user's computer may be able to decrypt a handful * of long-past messages (the first messages of an OTR * conversation). */ void (*timer_control)(void *opdata, unsigned int interval);
In order to prevent a forward secrecy violation, applications using libotr now need to be able to call otrl_message_poll on occasion. The simplest thing to do is just to set up a local timer that calls that function every definterval = otrl_message_poll_get_default_interval(userstate) seconds. To avoid unnecessary overhead, however, the timer_control callback is available. If you set timer_control to non-NULL, it will be called with instructions to turn on or off the periodic timer, and to what interval.
We have something similar with the session expiration.. should we revisit its design?
- Asynchronous Private Key Generation
An application that wants to begin asynchronous key generation calls the following method in libotr:
/* Begin a private key generation that will potentially take place in * a background thread. This routine must be called from the main * thread. It will set *newkeyp, which you can pass to * otrl_privkey_generate_calculate in a background thread. If it * returns gcry_error(GPG_ERR_EEXIST), then a privkey creation for * this accountname/protocol is already in progress, and *newkeyp will * be set to NULL. */ gcry_error_t otrl_privkey_generate_start(OtrlUserState us, const char *accountname, const char *protocol, void **newkeyp)
A background thread can call the following method with the structure that was passed into "newkeyp" above:
/* Do the private key generation calculation. You may call this from a * background thread. When it completes, call * otrl_privkey_generate_finish from the _main_ thread. */ gcry_error_t otrl_privkey_generate_calculate(void *newkey)
Upon completion the application would call:
/* Call this from the main thread only. It will write the newly created * private key into the given file and store it in the OtrlUserState. */ gcry_error_t otrl_privkey_generate_finish(OtrlUserState us, void *newkey, const char *filename)
If the privkey generation was cancelled, the application should call:
/* Call this from the main thread only, in the event that the background * thread generating the key is cancelled. The newkey is deallocated, * and must not be used further. */ void otrl_privkey_generate_cancelled(OtrlUserState us, void *newkey)
should we have something like this?