libfreefare/libfreefare/mifare_key_deriver.3
Robert Quattlebaum ec91014ebf Properly handle edge cases in AN10922 key diversification
This commit fixes issue .

[AN10922][] specifies the key diversification algorithms used by the
MIFARE SAM AV3. Support for these algorithms was added to
`libfreefare` via pull-request .

However, while every attempt was made to write a faithful
implementation, the implemented code did not properly handle cases
where the diversification data was less than or equal to the block
size of the cipher: 16 bytes for AES, and 8 bytes for DES. This
bug was identified in issue .

This commit addresses this problem while providing a way to revert to
the previous behavior in cases where it is necessary to maintain
previous deployments. This was accomplished by introducing a new
`flags` parameter to the `mifare_key_deriver_new_an10922` method.

Normally, `flags` should simply be set to `AN10922_FLAG_DEFAULT`.
However, if the previous behavior is required, it should be set to
`AN10922_FLAG_EMULATE_ISSUE_91`.

[AN10922][] does not include any test vectors that might have helped to
identify this problem earlier. However, [AN10957][] (pages 13-14) was
found to have a suitable example usage of [AN10922][] with an
appropriately short value for *M* that we are using as a test vector
to verify correct behavior.

Note that the issue being addressed here is not a security issue:
using the `AN10922_FLAG_EMULATE_ISSUE_91` should not be any less
secure than using `AN10922_FLAG_DEFAULT`.

[AN10922]: https://www.nxp.com/docs/en/application-note/AN10922.pdf
[AN10957]: https://www.nxp.com/docs/en/application-note/AN10957.pdf
2019-10-29 11:21:56 -07:00

173 lines
5.9 KiB
Groff

.\" Copyright (C) 2018 Robert Quattlebaum
.\"
.\" This program is free software: you can redistribute it and/or modify it
.\" under the terms of the GNU Lesser General Public License as published by the
.\" Free Software Foundation, either version 3 of the License, or (at your
.\" option) any later version.
.\"
.\" This program is distributed in the hope that it will be useful, but WITHOUT
.\" ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
.\" FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
.\" more details.
.\"
.\" You should have received a copy of the GNU Lesser General Public License
.\" along with this program. If not, see <http://www.gnu.org/licenses/>
.\"
.Dd January 4, 2018
.Dt MIFARE_KEY_DERIVER 3
.Os
.\" _ _
.\" | \ | | __ _ _ __ ___ ___
.\" | \| |/ _` | '_ ` _ \ / _ \
.\" | |\ | (_| | | | | | | __/
.\" |_| \_|\__,_|_| |_| |_|\___|
.\"
.Sh NAME
.Nm mifare_key_deriver_new_an10922 ,
.Nm mifare_key_deriver_begin ,
.Nm mifare_key_deriver_update_data ,
.Nm mifare_key_deriver_update_uid ,
.Nm mifare_key_deriver_update_aid ,
.Nm mifare_key_deriver_update_cstr ,
.Nm mifare_key_deriver_end ,
.Nm mifare_key_deriver_end_raw ,
.Nm mifare_key_deriver_free ,
.Nd Mifare Key Derivation Functions
.\" _ _ _
.\" | | (_) |__ _ __ __ _ _ __ _ _
.\" | | | | '_ \| '__/ _` | '__| | | |
.\" | |___| | |_) | | | (_| | | | |_| |
.\" |_____|_|_.__/|_| \__,_|_| \__, |
.\" |___/
.Sh LIBRARY
Mifare card manipulation library (libfreefare, \-lfreefare)
.\" ____ _
.\" / ___| _ _ _ __ ___ _ __ ___(_)___
.\" \___ \| | | | '_ \ / _ \| '_ \/ __| / __|
.\" ___) | |_| | | | | (_) | |_) \__ \ \__ \
.\" |____/ \__, |_| |_|\___/| .__/|___/_|___/
.\" |___/ |_|
.Sh SYNOPSIS
.In freefare.h
.Ft MifareKeyDeriver
.Fn mifare_key_deriver_new_an10922 "MifareDESFireKey master_key" "MifareKeyType output_key_type" "int flags"
.Ft int
.Fn mifare_key_deriver_begin "MifareKeyDeriver deriver"
.Ft int
.Fn mifare_key_deriver_update_data "MifareKeyDeriver deriver" "const uint8_t *data" "size_t len"
.Ft int
.Fn mifare_key_deriver_update_uid "MifareKeyDeriver deriver" "FreefareTag tag"
.Ft int
.Fn mifare_key_deriver_update_aid "MifareKeyDeriver deriver" "MifareDESFireAID aid"
.Ft int
.Fn mifare_key_deriver_update_cstr "MifareKeyDeriver deriver" "const char *cstr"
.Ft MifareDESFireKey
.Fn mifare_key_deriver_end "MifareKeyDeriver deriver"
.Ft int
.Fn mifare_key_deriver_end_raw "MifareKeyDeriver deriver" "uint8_t* derived_data" "size_t data_max_len"
.Ft void
.Fn mifare_key_deriver_free "MifareKeyDeriver deriver"
.\" ____ _ _ _
.\" | _ \ ___ ___ ___ _ __(_)_ __ | |_(_) ___ _ __
.\" | | | |/ _ \/ __|/ __| '__| | '_ \| __| |/ _ \| '_ \
.\" | |_| | __/\__ \ (__| | | | |_) | |_| | (_) | | | |
.\" |____/ \___||___/\___|_| |_| .__/ \__|_|\___/|_| |_|
.\" |_|
.Sh DESCRIPTION
The
.Fn mifare_key_deriver_*
family of functions allows for the diversification of Mifare DESFire keys.
.Pp
The
.Fn mifare_key_deriver_new_an10922
function alocates a new key deriver object which can be used to generate
diversified keys from
.Va master_key
in accordinance with AN10922 when the flags field is is set to AN10922_FLAG_DEFAULT.
When the flags field is set to AN10922_FLAG_EMULATE_ISSUE_91, the resulting key
deriver will use the non-AN10922-compliant key derivation that was originally being
used by this API. All new deployments should use AN10922_FLAG_DEFAULT. See issue #91 for
more information.
.Pp
The
.Fn mifare_key_deriver_begin
function marks the start of the derivation of a new diversified key.
.Pp
The
.Fn mifare_key_deriver_update_data ,
.Fn mifare_key_deriver_update_uid ,
.Fn mifare_key_deriver_update_aid
and
.Fn mifare_key_deriver_update_cstr
functions are used to specify the information that should be used to derive
the diversified key from the master key.
.Pp
The
.Fn mifare_key_deriver_end
function marks the end of the derivation and returns the new diversified key.
It is the responsibility of the caller to to free the returned key by calling
.Fn mifare_desfire_key_free .
.Fn mifare_key_deriver_end_raw
is a variant used to directly fetch the raw bytes of the derived key.
.Pp
.\" ____ _ _
.\" | _ \ ___| |_ _ _ _ __ _ __ __ ____ _| |_ _ ___ ___
.\" | |_) / _ \ __| | | | '__| '_ \ \ \ / / _` | | | | |/ _ \/ __|
.\" | _ < __/ |_| |_| | | | | | | \ V / (_| | | |_| | __/\__ \
.\" |_| \_\___|\__|\__,_|_| |_| |_| \_/ \__,_|_|\__,_|\___||___/
.\"
.Sh RETURN VALUES
.Fn mifare_key_deriver_new_an10922
returns the allocated key deriver or
.Va NULL
on failure.
.Pp
The
.Fn mifare_key_deriver_begin ,
.Fn mifare_key_deriver_update_data ,
.Fn mifare_key_deriver_update_uid ,
.Fn mifare_key_deriver_update_aid
and
.Fn mifare_key_deriver_update_cstr
functions return
.Va 0
on success and
.Va -1
on failure.
.Pp
The
.Fn mifare_key_deriver_end
function returns the new diversified key on success and
.Va NULL
on failure. It is the responsibility of the
caller to to free the returned key by calling
.Fn mifare_desfire_key_free .
.Pp
The
.Fn mifare_key_deriver_end_raw
function returns
.Va -1
on failure. On success, it returns the number of bytes that were derived. If
.Va data_max_len
is smaller than the return value, then no bytes were written to
.Va derived_data .
.Pp
Upon failure, all methods update
.Va errno
with the appropriate error code.
.\" ____ _
.\" / ___| ___ ___ __ _| |___ ___
.\" \___ \ / _ \/ _ \ / _` | / __|/ _ \
.\" ___) | __/ __/ | (_| | \__ \ (_) |
.\" |____/ \___|\___| \__,_|_|___/\___/
.\"
.Sh SEE ALSO
.Xr mifare_desfire_key 3
.\" _ _ _
.\" / \ _ _| |_| |__ ___ _ __ ___
.\" / _ \| | | | __| '_ \ / _ \| '__/ __|
.\" / ___ \ |_| | |_| | | | (_) | | \__ \
.\" /_/ \_\__,_|\__|_| |_|\___/|_| |___/
.\"
.Sh AUTHORS
.An Robert Quattlebaum darco@deepdarc.com