GSM A5 ciphering algorithm

## Files

file | a5.h

## Macros

#define | ENOTSUP EINVAL
#define | A5_R1_LEN 19
#define | A5_R2_LEN 22
#define | A5_R3_LEN 23
#define | A5_R4_LEN 17 /* A5/2 only */
#define | A5_R1_MASK ((1<<A5_R1_LEN)-1)
#define | A5_R2_MASK ((1<<A5_R2_LEN)-1)
#define | A5_R3_MASK ((1<<A5_R3_LEN)-1)
#define | A5_R4_MASK ((1<<A5_R4_LEN)-1)
#define | A5_R1_TAPS 0x072000 /* x^19 + x^18 + x^17 + x^14 + 1 */
#define | A5_R2_TAPS 0x300000 /* x^22 + x^21 + 1 */
#define | A5_R3_TAPS 0x700080 /* x^23 + x^22 + x^21 + x^8 + 1 */
#define | A5_R4_TAPS 0x010800 /* x^17 + x^12 + 1 */
#define | A51_R1_CLKBIT 0x000100
#define | A51_R2_CLKBIT 0x000400
#define | A51_R3_CLKBIT 0x000400
#define | A52_R4_CLKBIT0 0x000400
#define | A52_R4_CLKBIT1 0x000008
#define | A52_R4_CLKBIT2 0x000080

## Functions

static uint32_t | osmo_a5_fn_count (uint32_t fn)
| Converts a frame number into the 22 bit number used in A5/x. More...
int | osmo_a5 (int n, const uint8_t *key, uint32_t fn, ubit_t *dl, ubit_t *ul)
| Main method to generate a A5/x cipher stream. More...
void | osmo_a5_1 (const uint8_t *key, uint32_t fn, ubit_t *dl, ubit_t *ul) OSMO_DEPRECATED("Use generic osmo_a5() instead")
void | osmo_a5_2 (const uint8_t *key, uint32_t fn, ubit_t *dl, ubit_t *ul) OSMO_DEPRECATED("Use generic osmo_a5() instead")
void | _a5_4 (const uint8_t *ck, uint32_t fn, ubit_t *dl, ubit_t *ul, bool fn_correct)
| Generate a GSM A5/4 cipher stream. More...
void | _a5_3 (const uint8_t *key, uint32_t fn, ubit_t *dl, ubit_t *ul, bool fn_correct)
| Generate a GSM A5/3 cipher stream. More...
static uint32_t | _a5_12_parity (uint32_t x)
| Computes parity of a 32-bit word. More...
static uint32_t | _a5_12_majority (uint32_t v1, uint32_t v2, uint32_t v3)
| Compute majority bit from 3 taps. More...
static uint32_t | _a5_12_clock (uint32_t r, uint32_t mask, uint32_t taps)
| Compute the next LFSR state. More...
static void | _a5_1_clock (uint32_t r[], int force)
| GSM A5/1 Clocking function. More...
static uint8_t | _a5_1_get_output (uint32_t r[])
| GSM A5/1 Output function. More...
void | _a5_1 (const uint8_t *key, uint32_t fn, ubit_t *dl, ubit_t *ul)
| Generate a GSM A5/1 cipher stream. More...
static void | _a5_2_clock (uint32_t r[], int force)
| GSM A5/2 Clocking function. More...
static uint8_t | _a5_2_get_output (uint32_t r[])
| GSM A5/2 Output function. More...
void | _a5_2 (const uint8_t *key, uint32_t fn, ubit_t *dl, ubit_t *ul)
| Generate a GSM A5/1 cipher stream. More...

## Detailed Description

Osmocom GSM ciphering algorithm implementation

Full reimplementation of A5/1,2,3,4 (split and threadsafe).

The logic behind the algorithm is taken from "A pedagogical implementation of the GSM A5/1 and A5/2 "voice privacy" encryption algorithms." by Marc Briceno, Ian Goldberg, and David Wagner.

## Macro Definition Documentation

## A51_R1_CLKBIT

#define A51_R1_CLKBIT 0x000100

## A51_R2_CLKBIT

#define A51_R2_CLKBIT 0x000400

## A51_R3_CLKBIT

#define A51_R3_CLKBIT 0x000400

## A52_R4_CLKBIT0

#define A52_R4_CLKBIT0 0x000400

## A52_R4_CLKBIT1

#define A52_R4_CLKBIT1 0x000008

## A52_R4_CLKBIT2

#define A52_R4_CLKBIT2 0x000080

## A5_R1_LEN

#define A5_R1_LEN 19

## A5_R1_MASK

#define A5_R1_MASK ((1<<A5_R1_LEN)-1)

## A5_R1_TAPS

#define A5_R1_TAPS 0x072000 /* x^19 + x^18 + x^17 + x^14 + 1 */

## A5_R2_LEN

#define A5_R2_LEN 22

## A5_R2_MASK

#define A5_R2_MASK ((1<<A5_R2_LEN)-1)

## A5_R2_TAPS

#define A5_R2_TAPS 0x300000 /* x^22 + x^21 + 1 */

## A5_R3_LEN

#define A5_R3_LEN 23

## A5_R3_MASK

#define A5_R3_MASK ((1<<A5_R3_LEN)-1)

## A5_R3_TAPS

#define A5_R3_TAPS 0x700080 /* x^23 + x^22 + x^21 + x^8 + 1 */

## A5_R4_LEN

#define A5_R4_LEN 17 /* A5/2 only */

## A5_R4_MASK

#define A5_R4_MASK ((1<<A5_R4_LEN)-1)

## A5_R4_TAPS

#define A5_R4_TAPS 0x010800 /* x^17 + x^12 + 1 */

## ENOTSUP

#define ENOTSUP EINVAL

## Function Documentation

## _a5_1()

void _a5_1 | ( | const uint8_t * | key,
|  | uint32_t | fn,
|  | ubit_t * | dl,
|  | ubit_t * | ul
| ) |  |

Generate a GSM A5/1 cipher stream.

Parameters

  [in] | key | 8 byte array for the key (as received from the SIM)
  [in] | fn | Frame number
  [out] | dl | Pointer to array of ubits to return Downlink cipher stream
  [out] | ul | Pointer to array of ubits to return Uplink cipher stream

Either (or both) of dl/ul can be NULL if not needed.

References _a5_1_clock(), _a5_1_get_output(), and osmo_a5_fn_count().

Referenced by osmo_a5().

## _a5_12_clock()

static uint32_t _a5_12_clock | ( | uint32_t | r,
|  | uint32_t | mask,
|  | uint32_t | taps
| ) |  |

inline static

Compute the next LFSR state.

Parameters

  [in] | r | Current state
  [in] | mask | LFSR mask
  [in] | taps | LFSR taps

Returns
  Next state

References _a5_12_parity().

Referenced by _a5_1_clock(), and _a5_2_clock().

## _a5_12_majority()

static uint32_t _a5_12_majority | ( | uint32_t | v1,
|  | uint32_t | v2,
|  | uint32_t | v3
| ) |  |

inline static

Compute majority bit from 3 taps.

Parameters

  [in] | v1 | LFSR state ANDed with tap-bit
  [in] | v2 | LFSR state ANDed with tap-bit
  [in] | v3 | LFSR state ANDed with tap-bit

Returns
  The majority bit (0 or 1)

Referenced by _a5_1_clock(), and _a5_2_get_output().

## _a5_12_parity()

static uint32_t _a5_12_parity | ( | uint32_t | x | ) |

inline static

Computes parity of a 32-bit word.

Parameters

  [in] | x | 32 bit word

Returns
  Parity bit (xor of all bits) as 0 or 1

Referenced by _a5_12_clock().

## _a5_1_clock()

static void _a5_1_clock | ( | uint32_t | r[],
|  | int | force
| ) |  |

inline static

GSM A5/1 Clocking function.

Parameters

  [in] | r | Register state
  [in] | force | Non-zero value disable conditional clocking

References _a5_12_clock(), _a5_12_majority(), A51_R1_CLKBIT, A51_R2_CLKBIT, A51_R3_CLKBIT, A5_R1_MASK, A5_R1_TAPS, A5_R2_MASK, A5_R2_TAPS, A5_R3_MASK, and A5_R3_TAPS.

Referenced by _a5_1().

## _a5_1_get_output()

static uint8_t _a5_1_get_output | ( | uint32_t | r[] | ) |

inline static

GSM A5/1 Output function.

Parameters

  [in] | r | Register state

Returns
  The A5/1 output function bit

References A5_R1_LEN, A5_R2_LEN, and A5_R3_LEN.

Referenced by _a5_1().

## _a5_2()

void _a5_2 | ( | const uint8_t * | key,
|  | uint32_t | fn,
|  | ubit_t * | dl,
|  | ubit_t * | ul
| ) |  |

Generate a GSM A5/1 cipher stream.

Parameters

  [in] | key | 8 byte array for the key (as received from the SIM)
  [in] | fn | Frame number
  [out] | dl | Pointer to array of ubits to return Downlink cipher stream
  [out] | ul | Pointer to array of ubits to return Uplink cipher stream

Either (or both) of dl/ul can be NULL if not needed.

References _a5_2_clock(), _a5_2_get_output(), and osmo_a5_fn_count().

Referenced by osmo_a5().

## _a5_2_clock()

static void _a5_2_clock | ( | uint32_t | r[],
|  | int | force
| ) |  |

inline static

GSM A5/2 Clocking function.

Parameters

  [in] | r | Register state
  [in] | force | Non-zero value disable conditional clocking

References _a5_12_clock(), A52_R4_CLKBIT0, A52_R4_CLKBIT1, A52_R4_CLKBIT2, A5_R1_MASK, A5_R1_TAPS, A5_R2_MASK, A5_R2_TAPS, A5_R3_MASK, A5_R3_TAPS, A5_R4_MASK, and A5_R4_TAPS.

Referenced by _a5_2().

## _a5_2_get_output()

static uint8_t _a5_2_get_output | ( | uint32_t | r[] | ) |

inline static

GSM A5/2 Output function.

Parameters

  [in] | r | Register state

Returns
  The A5/2 output function bit

References _a5_12_majority(), A5_R1_LEN, A5_R2_LEN, and A5_R3_LEN.

Referenced by _a5_2().

## _a5_3()

void _a5_3 | ( | const uint8_t * | key,
|  | uint32_t | fn,
|  | ubit_t * | dl,
|  | ubit_t * | ul,
|  | bool | fn_correct
| ) |  |

Generate a GSM A5/3 cipher stream.

Parameters

  [in] | key | 8 byte array for the key (as received from the SIM)
  [in] | fn | Frame number
  [out] | dl | Pointer to array of ubits to return Downlink cipher stream
  [out] | ul | Pointer to array of ubits to return Uplink cipher stream
  [in] | fn_correct | true if fn is a real GSM frame number and thus requires internal conversion

Either (or both) of dl/ul should be NULL if not needed.

Implementation based on specifications from 3GPP TS 55.216, 3GPP TR 55.919 and ETSI TS 135 202 with slight simplifications (CE hardcoded to 0).

References _a5_4(), and osmo_c4().

Referenced by osmo_a5().

## _a5_4()

void _a5_4 | ( | const uint8_t * | ck,
|  | uint32_t | fn,
|  | ubit_t * | dl,
|  | ubit_t * | ul,
|  | bool | fn_correct
| ) |  |

Generate a GSM A5/4 cipher stream.

Parameters

  [in] | key | 16 byte array for the key (as received from the SIM)
  [in] | fn | Frame number
  [out] | dl | Pointer to array of ubits to return Downlink cipher stream
  [out] | ul | Pointer to array of ubits to return Uplink cipher stream
  [in] | fn_correct | true if fn is a real GSM frame number and thus requires internal conversion

Either (or both) of dl/ul should be NULL if not needed.

Implementation based on specifications from 3GPP TS 55.216, 3GPP TR 55.919 and ETSI TS 135 202 with slight simplifications (CE hardcoded to 0).

References _kasumi_kgcore(), and osmo_a5_fn_count().

Referenced by _a5_3(), and osmo_a5().

## osmo_a5()

int osmo_a5 | ( | int | n,
|  | const uint8_t * | key,
|  | uint32_t | fn,
|  | ubit_t * | dl,
|  | ubit_t * | ul
| ) |  |

Main method to generate a A5/x cipher stream.

Parameters

  [in] | n | Which A5/x method to use
  [in] | key | 8 or 16 (for a5/4) byte array for the key (as received from the SIM)
  [in] | fn | Frame number
  [out] | dl | Pointer to array of ubits to return Downlink cipher stream
  [out] | ul | Pointer to array of ubits to return Uplink cipher stream

Returns
  0 for success, -ENOTSUP for invalid cipher selection.

Currently A5/[0-4] are supported. Either (or both) of dl/ul can be NULL if not needed.

References _a5_1(), _a5_2(), _a5_3(), _a5_4(), and ENOTSUP.

Referenced by osmo_a5_1(), and osmo_a5_2().

## osmo_a5_1()

void osmo_a5_1 | ( | const uint8_t * | key,
|  | uint32_t | fn,
|  | ubit_t * | dl,
|  | ubit_t * | ul
| ) |  |

References osmo_a5().

## osmo_a5_2()

void osmo_a5_2 | ( | const uint8_t * | key,
|  | uint32_t | fn,
|  | ubit_t * | dl,
|  | ubit_t * | ul
| ) |  |

References osmo_a5().

## osmo_a5_fn_count()

static uint32_t osmo_a5_fn_count | ( | uint32_t | fn | ) |

inline static

Converts a frame number into the 22 bit number used in A5/x.

Parameters

  [in] | fn | The true framenumber

Returns
  22 bit word

References t1, t2, and t3.

Referenced by _a5_1(), _a5_2(), and _a5_4().