ARPA2 Common Libraries  2.2.25
Macros | Typedefs | Enumerations | Functions
Signatures on ARPA2 Identities
Collaboration diagram for Signatures on ARPA2 Identities:

Macros

#define A2ID_SIGFLAG_EXPIRATION   ( 1 << A2ID_SIGDATA_EXPIRATION )
 
#define A2ID_SIGFLAG_REMOTE_DOMAIN   ( 1 << A2ID_SIGDATA_REMOTE_DOMAIN )
 
#define A2ID_SIGFLAG_REMOTE_USERID   ( 1 << A2ID_SIGDATA_REMOTE_USERID )
 
#define A2ID_SIGFLAG_LOCAL_ALIASES   ( 1 << A2ID_SIGDATA_LOCAL_ALIASES )
 
#define A2ID_SIGFLAG_SESSIONID   ( 1 << A2ID_SIGDATA_SESSIONID )
 
#define A2ID_SIGFLAG_SUBJECT   ( 1 << A2ID_SIGDATA_SUBJECT )
 
#define A2ID_SIGFLAG_TOPIC   ( 1 << A2ID_SIGDATA_TOPIC )
 
#define A2ID_SIGFLAG_CRYPTLOCAL   ( 1 << A2ID_SIGDATA_CRYPTLOCAL )
 

Typedefs

typedef bool a2id_sigdata_cb(a2id_sigdata_t sd, void *cbdata, const a2id_t *id, uint8_t *buf, uint16_t *buflen)
 Callback function prototype to retrieve signature data. More...
 

Enumerations

enum  a2id_sigdata_t {
  A2ID_SIGDATA_EXPIRATION , A2ID_SIGDATA_REMOTE_DOMAIN , A2ID_SIGDATA_REMOTE_USERID , A2ID_SIGDATA_LOCAL_ALIASES ,
  A2ID_SIGDATA_SESSIONID , A2ID_SIGDATA_SUBJECT , A2ID_SIGDATA_TOPIC , A2ID_SIGDATA_CRYPTLOCAL ,
  A2ID_SIGDATA_COUNT
}
 Signature data types. More...
 

Functions

bool a2id_addkey (int keyfd)
 Add a key to be used for signed identities. More...
 
void a2id_dropkeys (void)
 Wipe all keys clean. More...
 
bool a2id_sigdata_base (a2id_sigdata_t sd, void *cbdata_rid, const a2id_t *lid, uint8_t *buf, uint16_t *buflen)
 Basic callback function for a signed ARPA2 Identity. More...
 
bool a2id_sign (a2id_t *tbs, a2id_sigdata_cb cb, void *cbdata)
 Possibly attach a signature to an ARPA2 Identity, by adding extra characters to its username. More...
 
bool a2id_verify (a2id_t *a2id_to_be_verified, a2id_sigdata_cb cb, void *cbdata)
 Try to verify a signature on an ARPA2 Identity. More...
 

Detailed Description

Typedef Documentation

◆ a2id_sigdata_cb

typedef bool a2id_sigdata_cb(a2id_sigdata_t sd, void *cbdata, const a2id_t *id, uint8_t *buf, uint16_t *buflen)

Callback function prototype to retrieve signature data.

It receives both the identity structure and the signature requester's cbdata pointer to retrieve data. A sigdata code indicates what data to pass.

No more bytes than the original *buflen are written to buf, and if buf is NULL nothing must be written.

In all cases, *buflen is updated to the actual data size. This includes:

  • when buf was supplied as NULL
  • when not all data fitted into buf
  • regardless of the original *buflen value
  • when the data is unavailable, set *buflen to 0

In all cases, the function returns true when it has been able to supply the data, and is happy that it held enough bytes. The new value of *buflen leave the signature routines the choice to call again to fill a larger buffer instead. If it always wants to take this approach, the signer might first probe for the data size to use by calling with buf set to NULL.

The remaining cases are not so happy, and false is returned. This includes the cases where

  • the value of buf was NULL
  • the requested data could not be found
  • the original value of *buflen was too low

The signature algorithm can choose how to handle a false return value; it may try again, decide that the data is not important enough or break off the signature computation.

Enumeration Type Documentation

◆ a2id_sigdata_t

Signature data types.

These are managed in a repository, but since signatures are validated on the same place as they are made it does not really matter whether this is followed. Only for reasons of software compatibility is it quite useful to have a standard.

The registry is located at http://a2id.arpa2.org/sigflags.html

Function Documentation

◆ a2id_addkey()

bool a2id_addkey ( int  keyfd)

Add a key to be used for signed identities.

The last key added will be used for signatures. Keys added before it only serve as a validation option. Call this function as part of your initialisation, then try to drop privileges to reach the key material.

The key is read from a file descriptor, and should not exceed PIPE_BUF from <limits.h> in size. This construct allows you to load from a pipe or fifo, which can usually be read only once. Keys should fit easily into even the minimum PIPE_BUF in POSIX specifications.

Keys are obtained in a single read, and should end in a newline (a simple completeness check). Small sizes are considered an error. The key starts as "arpa2id", comma, 3-level semantic version for the first software to define the signature computation, comma, algorithm name, comma, and finally the key's entropy in any desired form desired. We like to use BASE32 but are mindful of case sensitivity of this input.

The file descriptor is not closed in this function; you may continue to use it for other purposes.

◆ a2id_dropkeys()

void a2id_dropkeys ( void  )

Wipe all keys clean.

Do not return the memory to the pool, but on a recycling list so those zeroes seem really important to the compiler.

◆ a2id_sigdata_base()

bool a2id_sigdata_base ( a2id_sigdata_t  sd,
void *  cbdata_rid,
const a2id_t lid,
uint8_t *  buf,
uint16_t *  buflen 
)

Basic callback function for a signed ARPA2 Identity.

The code of this function doubles as example code for an application-defined callback function; these may wrap around this function to not have to replicate these basic callback functions.

This function behaves as may be expected from a a2id_sigdata_cb typed function and can indeed be provided as such a callback to a2id_sign() and a2id_verify() functions. More elaborate callback functions may also use the code provided herein to derive the intended signature data.

This function expects the remote as an a2id_t in its cbdata, and it receives the local ARPA2 Identity from the a2id_sign() or a2id_verify() operation, and with that it can provide this sigdata:

  • A2ID_SIGDATA_REMOTE_DOMAIN
  • A2ID_SIGDATA_REMOTE_USERID
  • A2ID_SIGDATA_LOCAL_ALIASES

◆ a2id_sign()

bool a2id_sign ( a2id_t tbs,
a2id_sigdata_cb  cb,
void *  cbdata 
)

Possibly attach a signature to an ARPA2 Identity, by adding extra characters to its username.

This silently succeeds when there no key was loaded, and/or when the identity has no signature flags requesting for data to be incorporated.

The intention is to make it straightforward to integrate this call in every outgoing path, so that services will facilitate signatures and leave the choice to clients. Signature flags are gathered from an address provided by the local client, and both it and the expiration may be clipped to minimum and maximum values by the software before passing it in here.

A service that always calls a2id_sign() on outgoing traffic should also always call a2id_verify() on incoming traffic. This function is similarly permissive; users may require signatures (on some aliases) through their ACL.

A signature would expand the length of the identity so its local-part may span up to the 64 available characters.

When the signature was requested and could be constructed, return true and modify the tbs Identity. When signing failed, return false and unmodified buffer contents.

The callback function will be called, with its private data pointer, to retrieve context-dependent data from the surrounding application. This data may involve the (stylised) content of subject headers, topics, ... as defined in the sigdata enumeration type.

Services will want to constrain the sigflags field to the values that they can support before calling a2id_sign(). The sigflags is an OR-ed combination of A2ID_SIGFLAG_xxx.

When flagging A2ID_SIGFLAG_EXPIRATION, provide a time on the last valid day after today in expiration. The a2id_sign() routine trims the value to a day number since the 18000'th day after Jan 1st, 1970.

Keys are supposed to be fixed in a server, and they are found through static global variables. You initially load them with a2id_addkey() before dropping privileges.

◆ a2id_verify()

bool a2id_verify ( a2id_t a2id_to_be_verified,
a2id_sigdata_cb  cb,
void *  cbdata 
)

Try to verify a signature on an ARPA2 Identity.

An absent signature returns successfully, because it is left to later ACL filters to decide if a signature is required. When this service did not add keys it is assumed that verification is done elsewehre.

After returning successfully, the value in sigflags indicates the flags that have been validated; this is zeroed when nothing was validated. Likewise, the value returned in expiration is set after the day at which the signature expires.

Because it is so lenient, it is safe to always call a2id_verify() on the incoming path. This pairs up with always calling a2id_sign() on the outgoing path. To the client, signatures are a feature that they can choose to configure, if and where they desire it.

Situations that do lead to errors being returned are those where an address holds a signed Identity and at least one key has been added to this server. Multiple keys may be loaded to allow for rollover procedures, but when none validate the signature then a failure is reported. In this case, the sigflags are also zeroed to spread no certainty.

Some applications will want to enforce signatures. They might look at the returned value in *sigflags and at least test it to be non-zero, or they might use an ARPA2 Selector that contains the signature flags portion FLG in its grammar. When sigflags contiains A2ID_SIGFLAG_EXPIRATION, then expiration is checked to not have passed.

Keys are supposed to be fixed in a server, and they are found through static global variables. You initially load them with a2id_addkey() before dropping privileges.