cwist
Modern C web framework with libttak runtime
Loading...
Searching...
No Matches
ice.c File Reference

Minimal STUN/ICE (RFC 5389 / RFC 8445) for the ICE-lite agent. More...

#include "webrtc_internal.h"
#include <openssl/evp.h>
#include <openssl/hmac.h>
#include <openssl/rand.h>
#include <string.h>
Include dependency graph for ice.c:

Go to the source code of this file.

Macros

STUN wire-format constants (RFC 5389)
#define STUN_MAGIC   0x2112A442u
 
#define STUN_HDR_LEN   20
 
#define ATTR_MAPPED_ADDRESS   0x0001
 
#define ATTR_USERNAME   0x0006
 
#define ATTR_MESSAGE_INTEGRITY   0x0008
 
#define ATTR_PRIORITY   0x0024
 
#define ATTR_USE_CANDIDATE   0x0025
 
#define ATTR_XOR_MAPPED_ADDRESS   0x0020
 
#define ATTR_FINGERPRINT   0x8028
 
#define ATTR_ICE_CONTROLLED   0x8029
 
#define ATTR_ICE_CONTROLLING   0x802A
 

Typedefs

typedef bool(* attr_cb) (uint16_t type, const uint8_t *val, uint16_t val_len, void *arg)
 

Functions

int cwist_ice_stun_is_message (const uint8_t *buf, size_t len)
 Check whether a datagram looks like a STUN message.
 
bool cwist_ice_stun_is_binding_request (const uint8_t *buf, size_t len)
 Check whether a datagram is a STUN binding request.
 
bool cwist_ice_stun_has_use_candidate (const uint8_t *buf, size_t len)
 Check whether a STUN message carries the USE-CANDIDATE attribute.
 
int cwist_ice_stun_validate_request (const uint8_t *buf, size_t len, const char *pwd)
 Validate the MESSAGE-INTEGRITY of a STUN message against a password.
 
int cwist_ice_stun_build_response (uint8_t *out, size_t cap, const uint8_t *req, size_t req_len, const struct sockaddr_in *mapped, const char *pwd)
 Build a STUN binding response for a received binding request.
 
int cwist_ice_stun_build_request (uint8_t *out, size_t cap, const uint8_t txid[12], const char *username)
 Build an unsigned ICE-controlling STUN binding request.
 
int cwist_ice_stun_sign_request (uint8_t *msg, size_t cap, size_t msg_len, const char *pwd)
 Public wrapper around stun_sign() for signing a built binding request.
 
int cwist_ice_stun_parse_response (const uint8_t *buf, size_t len, const uint8_t txid[12], const char *pwd, struct sockaddr_in *mapped)
 Validate a received STUN binding response.
 
int cwist_ice_stun_get_remote_ufrag (const uint8_t *buf, size_t len, char *out, size_t cap)
 Extract the sender's ufrag from the USERNAME attribute of a STUN message.
 
void cwist_ice_random_creds (char *ufrag, size_t ufrag_cap, char *pwd, size_t pwd_cap)
 Generate random ICE ufrag/pwd credentials.
 

Detailed Description

Minimal STUN/ICE (RFC 5389 / RFC 8445) for the ICE-lite agent.

Implements just enough of STUN message parsing, validation, and construction to run an ICE-lite endpoint: binding request/response handling, MESSAGE-INTEGRITY (HMAC-SHA1) and FINGERPRINT (CRC-32) generation and checking, XOR-MAPPED-ADDRESS extraction, and random ICE credential generation. No retransmission or state machine logic lives here; callers in webrtc.c drive timing and nomination.

Definition in file ice.c.

Macro Definition Documentation

◆ ATTR_FINGERPRINT

#define ATTR_FINGERPRINT   0x8028

FINGERPRINT attribute type (CRC-32 xor 0x5354554E).

Definition at line 28 of file ice.c.

◆ ATTR_ICE_CONTROLLED

#define ATTR_ICE_CONTROLLED   0x8029

ICE-CONTROLLED attribute type. Unused by this agent.

Definition at line 29 of file ice.c.

◆ ATTR_ICE_CONTROLLING

#define ATTR_ICE_CONTROLLING   0x802A

ICE-CONTROLLING attribute type (we always send it).

Definition at line 30 of file ice.c.

◆ ATTR_MAPPED_ADDRESS

#define ATTR_MAPPED_ADDRESS   0x0001

MAPPED-ADDRESS attribute type. Unused (we send XOR-MAPPED-ADDRESS).

Definition at line 22 of file ice.c.

◆ ATTR_MESSAGE_INTEGRITY

#define ATTR_MESSAGE_INTEGRITY   0x0008

MESSAGE-INTEGRITY attribute type (HMAC-SHA1, 20 bytes).

Definition at line 24 of file ice.c.

◆ ATTR_PRIORITY

#define ATTR_PRIORITY   0x0024

PRIORITY attribute type (ICE, RFC 8445).

Definition at line 25 of file ice.c.

◆ ATTR_USE_CANDIDATE

#define ATTR_USE_CANDIDATE   0x0025

USE-CANDIDATE attribute type (nomination hint).

Definition at line 26 of file ice.c.

◆ ATTR_USERNAME

#define ATTR_USERNAME   0x0006

USERNAME attribute type ("remoteufrag:localufrag").

Definition at line 23 of file ice.c.

◆ ATTR_XOR_MAPPED_ADDRESS

#define ATTR_XOR_MAPPED_ADDRESS   0x0020

XOR-MAPPED-ADDRESS attribute type.

Definition at line 27 of file ice.c.

◆ STUN_HDR_LEN

#define STUN_HDR_LEN   20

Fixed STUN message header size in bytes.

Definition at line 21 of file ice.c.

◆ STUN_MAGIC

#define STUN_MAGIC   0x2112A442u

Magic cookie; also the XOR mask for addresses/ports.

Definition at line 20 of file ice.c.

Typedef Documentation

◆ attr_cb

typedef bool(* attr_cb) (uint16_t type, const uint8_t *val, uint16_t val_len, void *arg)

Callback invoked once per STUN attribute during a walk_attrs() scan.

Parameters
typeAttribute type field.
valPointer to the attribute value inside the message buffer.
val_lenValue length in bytes (unpadded).
argOpaque pointer supplied to walk_attrs().
Return values
trueContinue walking.
falseStop walking (walk_attrs() then reports failure to its caller).

Definition at line 131 of file ice.c.

Function Documentation

◆ cwist_ice_random_creds()

void cwist_ice_random_creds ( char *  ufrag,
size_t  ufrag_cap,
char *  pwd,
size_t  pwd_cap 
)

Generate random ICE ufrag/pwd credentials.

Generate random ICE credentials (ice-chars only).

Both strings are drawn from 24 bytes of CSPRNG output encoded with the base64url alphabet (6 bits per character).

Parameters
ufragOutput buffer for the ufrag.
ufrag_capCapacity of ufrag; up to 8 characters plus NUL are written.
pwdOutput buffer for the password.
pwd_capCapacity of pwd; up to 32 characters plus NUL are written.
Warning
Behavior is undefined if either capacity is 0 (cap - 1 underflows).

Definition at line 592 of file ice.c.

References cap, and RAND_bytes.

◆ cwist_ice_stun_build_request()

int cwist_ice_stun_build_request ( uint8_t *  out,
size_t  cap,
const uint8_t  txid[12],
const char *  username 
)

Build an unsigned ICE-controlling STUN binding request.

Build an unsigned Binding request (USERNAME, USE-CANDIDATE, ...).

The request carries USERNAME (only if username is non-empty), ICE-CONTROLLING, USE-CANDIDATE, and PRIORITY attributes. MESSAGE-INTEGRITY and FINGERPRINT are intentionally not added here; the MI key (the peer's password) is only known at send time, so the caller signs the built request with cwist_ice_stun_sign_request().

Parameters
outDestination buffer.
capCapacity of out in bytes.
txid12-byte transaction ID to copy into the header.
username"remoteufrag:localufrag" string for the USERNAME attribute; skipped when empty.
Returns
Total request length in bytes, or -1 if cap is too small.

Definition at line 361 of file ice.c.

References ATTR_ICE_CONTROLLING, ATTR_PRIORITY, ATTR_USE_CANDIDATE, ATTR_USERNAME, cap, CWIST_STUN_BINDING_REQUEST, STUN_HDR_LEN, and STUN_MAGIC.

◆ cwist_ice_stun_build_response()

int cwist_ice_stun_build_response ( uint8_t *  out,
size_t  cap,
const uint8_t *  req,
size_t  req_len,
const struct sockaddr_in *  mapped,
const char *  pwd 
)

Build a STUN binding response for a received binding request.

Build a signed Binding success response with XOR-MAPPED-ADDRESS.

Emits a message containing XOR-MAPPED-ADDRESS (IPv4 only), MESSAGE-INTEGRITY (HMAC-SHA1 keyed with pwd), and FINGERPRINT attributes, reusing the request's transaction ID.

Parameters
outDestination buffer.
capCapacity of out in bytes.
reqThe received binding request (used for its transaction ID).
req_lenBytes at req; currently unused.
mappedAddress/port to report back (XOR-encoded with the magic cookie).
pwdShort-term credential password for the MI HMAC.
Returns
Total response length in bytes, or -1 if cap is too small or OpenSSL allocation fails.

Definition at line 281 of file ice.c.

References ATTR_FINGERPRINT, ATTR_MESSAGE_INTEGRITY, ATTR_XOR_MAPPED_ADDRESS, cap, CWIST_STUN_BINDING_RESPONSE, HMAC_CTX_free, HMAC_CTX_new, HMAC_Final, HMAC_Init_ex, HMAC_Update, STUN_HDR_LEN, and STUN_MAGIC.

◆ cwist_ice_stun_get_remote_ufrag()

int cwist_ice_stun_get_remote_ufrag ( const uint8_t *  buf,
size_t  len,
char *  out,
size_t  cap 
)

Extract the sender's ufrag from the USERNAME attribute of a STUN message.

Extract the sender's ufrag from USERNAME ("recipient:sender", RFC 8445 section 7.2.2) – the peer's SDP ice-ufrag.

A Binding request's USERNAME is "<recipient ufrag>:<sender ufrag>" (RFC 8445 section 7.2.2), so for a request we received this returns the part after the first ':' – the remote peer's ufrag, as it appears in the peer's SDP.

Parameters
bufDatagram bytes.
lenNumber of bytes at buf.
outOutput buffer for the NUL-terminated ufrag.
capCapacity of out; output is truncated to cap - 1 characters.
Return values
0Ufrag extracted (possibly truncated).
-1Not a STUN message, or no USERNAME attribute present.

Definition at line 556 of file ice.c.

References ATTR_USERNAME, cap, cwist_ice_stun_is_message(), and STUN_HDR_LEN.

◆ cwist_ice_stun_has_use_candidate()

bool cwist_ice_stun_has_use_candidate ( const uint8_t *  buf,
size_t  len 
)

Check whether a STUN message carries the USE-CANDIDATE attribute.

true if the request carries USE-CANDIDATE (nomination).

Parameters
bufDatagram bytes.
lenNumber of bytes at buf.

Definition at line 197 of file ice.c.

References ATTR_USE_CANDIDATE.

◆ cwist_ice_stun_is_binding_request()

bool cwist_ice_stun_is_binding_request ( const uint8_t *  buf,
size_t  len 
)

Check whether a datagram is a STUN binding request.

true if buf is a STUN Binding request.

Parameters
bufDatagram bytes.
lenNumber of bytes at buf.
Returns
true if buf is a STUN message with type CWIST_STUN_BINDING_REQUEST.

Definition at line 119 of file ice.c.

References cwist_ice_stun_is_message(), and CWIST_STUN_BINDING_REQUEST.

◆ cwist_ice_stun_is_message()

int cwist_ice_stun_is_message ( const uint8_t *  buf,
size_t  len 
)

Check whether a datagram looks like a STUN message.

Non-zero if buf looks like a STUN message (magic cookie, length).

Parameters
bufDatagram bytes.
lenNumber of bytes at buf.
Returns
1 if buf holds at least a STUN header and the magic cookie matches, 0 otherwise.
Note
This is a shape check only; no attribute parsing or auth is performed.

Definition at line 110 of file ice.c.

References STUN_HDR_LEN, and STUN_MAGIC.

Referenced by cwist_ice_stun_get_remote_ufrag(), cwist_ice_stun_is_binding_request(), cwist_ice_stun_parse_response(), and cwist_ice_stun_validate_request().

◆ cwist_ice_stun_parse_response()

int cwist_ice_stun_parse_response ( const uint8_t *  buf,
size_t  len,
const uint8_t  txid[12],
const char *  pwd,
struct sockaddr_in *  mapped 
)

Validate a received STUN binding response.

Validate a response: cookie, txid match, MI with pwd, return mapped address.

Checks, in order: well-formed STUN message of type BINDING-RESPONSE, transaction ID match against txid, MESSAGE-INTEGRITY HMAC with pwd (via cwist_ice_stun_validate_request()), and presence of a MESSAGE-INTEGRITY attribute. If mapped is non-NULL, an IPv4 XOR-MAPPED-ADDRESS must also be present and is decoded into it.

Parameters
bufDatagram bytes.
lenNumber of bytes at buf.
txidTransaction ID the response must carry (the one we sent).
pwdLocal password used as the MI HMAC key.
mappedOptional output for the decoded mapped address.
Return values
1Valid response.
0Any check failed or the message is malformed.

Definition at line 518 of file ice.c.

References cap, cwist_ice_stun_is_message(), cwist_ice_stun_validate_request(), and CWIST_STUN_BINDING_RESPONSE.

◆ cwist_ice_stun_sign_request()

int cwist_ice_stun_sign_request ( uint8_t *  msg,
size_t  cap,
size_t  msg_len,
const char *  pwd 
)

Public wrapper around stun_sign() for signing a built binding request.

Append MESSAGE-INTEGRITY and FINGERPRINT to a request.

Parameters
msgBuffer holding the request; extended in place.
capTotal capacity of msg.
msg_lenCurrent request length.
pwdPeer password used as the MI HMAC key.
Returns
New total length, or -1 on failure (see stun_sign()).

Definition at line 474 of file ice.c.

References cap.

◆ cwist_ice_stun_validate_request()

int cwist_ice_stun_validate_request ( const uint8_t *  buf,
size_t  len,
const char *  pwd 
)

Validate the MESSAGE-INTEGRITY of a STUN message against a password.

Check MESSAGE-INTEGRITY (HMAC-SHA1 keyed with pwd).

Parameters
bufDatagram bytes (any STUN message type; also used for responses).
lenNumber of bytes at buf.
pwdShort-term credential password used as the HMAC-SHA1 key.
Returns
1 if the HMAC matches, 0 if the message is malformed, the HMAC does not match, or OpenSSL allocation fails.
Return values
1Also when no MESSAGE-INTEGRITY attribute is present: accepted for MVP interoperability (RFC 8445 requires MI, but the agent stays permissive here).
Note
The HMAC covers the message up to and including the MI attribute header, with the header's length field adjusted to end at the MI attribute, per RFC 5389.

Definition at line 241 of file ice.c.

References cap, cwist_ice_stun_is_message(), EVP_MAX_MD_SIZE, HMAC_CTX_free, HMAC_CTX_new, HMAC_Final, HMAC_Init_ex, HMAC_Update, and STUN_HDR_LEN.

Referenced by cwist_ice_stun_parse_response().