Petri Hintukainen pushed to branch master at VideoLAN / libaacs
Commits: 7c804ad3 by Petri Hintukainen at 2021-05-01T19:41:46+03:00 crypto: check for gcrypt AES errors - - - - - 554601de by Petri Hintukainen at 2021-05-01T20:09:06+03:00 mmc: log gcrypt AES errors - - - - - de0f0c84 by Petri Hintukainen at 2021-05-01T20:13:40+03:00 mkb: Return record length only when valid record was found. - - - - - 4 changed files: - src/libaacs/crypto.c - src/libaacs/crypto.h - src/libaacs/mkb.c - src/libaacs/mmc.c Changes: ===================================== src/libaacs/crypto.c ===================================== @@ -106,18 +106,22 @@ static void _curve_free(elliptic_curve_t *c) point_free(&c->G); } -static void _aesg3(const uint8_t *src_key, uint8_t *dst_key, uint8_t inc) +BD_USED static int _aesg3(const uint8_t *src_key, uint8_t *dst_key, uint8_t inc) { - int a; + int a, err; uint8_t seed[16] = { 0x7B, 0x10, 0x3C, 0x5D, 0xCB, 0x08, 0xC4, 0xE5, 0x1A, 0x27, 0xB0, 0x17, 0x99, 0x05, 0x3B, 0xD9 }; seed[15] += inc; - crypto_aes128d(src_key, seed, dst_key); + err = crypto_aes128d(src_key, seed, dst_key); + if (err) + return err; for (a = 0; a < 16; a++) { dst_key[a] ^= seed[a]; } + + return err; } /* Initializes libgcrypt */ @@ -143,39 +147,61 @@ int crypto_init() return crypto_init_check; } -void crypto_aes128e(const uint8_t *key, const uint8_t *data, uint8_t *dst) +int crypto_aes128e(const uint8_t *key, const uint8_t *data, uint8_t *dst) { gcry_cipher_hd_t gcry_h; + gcry_error_t err; + + err = gcry_cipher_open(&gcry_h, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_ECB, 0); + if (err) + return err; + + err = gcry_cipher_setkey(gcry_h, key, 16); + if (err) + goto error; + err = gcry_cipher_encrypt(gcry_h, dst, 16, data, data ? 16 : 0); - gcry_cipher_open(&gcry_h, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_ECB, 0); - gcry_cipher_setkey(gcry_h, key, 16); - gcry_cipher_encrypt(gcry_h, dst, 16, data, data ? 16 : 0); + error: gcry_cipher_close(gcry_h); + return err; } -void crypto_aes128d(const uint8_t *key, const uint8_t *data, uint8_t *dst) +int crypto_aes128d(const uint8_t *key, const uint8_t *data, uint8_t *dst) { gcry_cipher_hd_t gcry_h; + gcry_error_t err; + + err = gcry_cipher_open(&gcry_h, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_ECB, 0); + if (err) + return err; - gcry_cipher_open(&gcry_h, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_ECB, 0); - gcry_cipher_setkey(gcry_h, key, 16); - gcry_cipher_decrypt(gcry_h, dst, 16, data, 16); + err = gcry_cipher_setkey(gcry_h, key, 16); + if (err) + goto error; + err = gcry_cipher_decrypt(gcry_h, dst, 16, data, 16); + + error: gcry_cipher_close(gcry_h); + return err; } -void crypto_aesg3(const uint8_t *D, uint8_t *lsubk, uint8_t* rsubk, uint8_t *pk) +int crypto_aesg3(const uint8_t *D, uint8_t *lsubk, uint8_t* rsubk, uint8_t *pk) { + int err1 = 0, err2 = 0, err3 = 0; + if (lsubk) { - _aesg3(D, lsubk, 0); + err1 = _aesg3(D, lsubk, 0); } if (pk) { - _aesg3(D, pk, 1); + err2 = _aesg3(D, pk, 1); } if (rsubk) { - _aesg3(D, rsubk, 2); + err3 = _aesg3(D, rsubk, 2); } + + return err1 ? err1 : err2 ? err2 : err3; } /* @@ -189,15 +215,18 @@ static void _shl_128(unsigned char *dst, const unsigned char *src) for (i = 15; i >= 0; i--) { dst[i] = (src[i] << 1) | overflow; - overflow = src[i] >> 7; + overflow = src[i] >> 7; } } -static void _cmac_key(const unsigned char *aes_key, unsigned char *k1, unsigned char *k2) +BD_USED static int _cmac_key(const unsigned char *aes_key, unsigned char *k1, unsigned char *k2) { uint8_t key[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + int err; - crypto_aes128e(aes_key, NULL, key); + err = crypto_aes128e(aes_key, NULL, key); + if (err) + return err; _shl_128(k1, key); if (key[0] & 0x80) { @@ -208,42 +237,81 @@ static void _cmac_key(const unsigned char *aes_key, unsigned char *k1, unsigned if (k1[0] & 0x80) { k2[15] ^= 0x87; } + + return err; } -void crypto_aes_cmac_16(const unsigned char *data, const unsigned char *aes_key, unsigned char *cmac) +int crypto_aes_cmac_16(const unsigned char *data, const unsigned char *aes_key, unsigned char *cmac) { uint8_t k1[16], k2[16]; unsigned ii; + int err; /* * Simplified version of AES CMAC. Spports only 16-byte input data. */ /* generate CMAC keys */ - _cmac_key(aes_key, k1, k2); + + err = _cmac_key(aes_key, k1, k2); + if (err) + return err; + memcpy(cmac, data, 16); for (ii = 0; ii < 16; ii++) { cmac[ii] ^= k1[ii]; } - crypto_aes128e(aes_key, NULL, cmac); + err = crypto_aes128e(aes_key, NULL, cmac); + + return err; } /* * */ -void crypto_aacs_decrypt(const uint8_t *key, uint8_t *out, size_t out_size, const uint8_t *in, size_t in_size) +int crypto_aacs_decrypt(const uint8_t *key, uint8_t *out, size_t out_size, const uint8_t *in, size_t in_size) { static const uint8_t aacs_iv[16] = { 0x0b, 0xa0, 0xf8, 0xdd, 0xfe, 0xa6, 0x1f, 0xb3, 0xd8, 0xdf, 0x9f, 0x56, 0x6a, 0x05, 0x0f, 0x78 }; gcry_cipher_hd_t gcry_h; + gcry_error_t err; + + err = gcry_cipher_open(&gcry_h, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_CBC, 0); + if (err) + return err; - gcry_cipher_open(&gcry_h, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_CBC, 0); - gcry_cipher_setkey(gcry_h, key, 16); - gcry_cipher_setiv(gcry_h, aacs_iv, 16); - gcry_cipher_decrypt(gcry_h, out, out_size, in, in_size); + err = gcry_cipher_setkey(gcry_h, key, 16); + if (err) + goto error; + err = gcry_cipher_setiv(gcry_h, aacs_iv, 16); + if (err) + goto error; + err = gcry_cipher_decrypt(gcry_h, out, out_size, in, in_size); + + error: gcry_cipher_close(gcry_h); + return err; +} + +/* + * + */ + +void crypto_strerror(int err, char *buf, size_t buf_size) +{ +#if defined(HAVE_STRERROR_R) && defined(HAVE_LIBGPG_ERROR) + buf[0] = 0; + gpg_strerror_r(err, buf, buf_size); +#else + const char *msg = gcry_strerror(err); + buf[0] = 0; + if (str) { + strncpy(buf, str, buf_size); + str[buf_size - 1] = 0; + } +#endif } /* ===================================== src/libaacs/crypto.h ===================================== @@ -25,14 +25,21 @@ #include <stdlib.h> #include <stdint.h> +BD_PRIVATE void crypto_strerror(int err, char *buf, size_t buf_size); +#define LOG_CRYPTO_ERROR(flags, str, err) do { \ + char s[64]; \ + crypto_strerror((err), s, sizeof(s)); \ + BD_DEBUG(DBG_CRIT | (flags), "crypto error: %s: %s (%u)\n", (str), s, (unsigned)(err)); \ + } while (0) + BD_PRIVATE int crypto_init(void); -BD_PRIVATE void crypto_aes128e(const uint8_t *key, const uint8_t *data, uint8_t *dst); -BD_PRIVATE void crypto_aes128d(const uint8_t *key, const uint8_t *data, uint8_t *dst); -BD_PRIVATE void crypto_aesg3(const uint8_t *D, uint8_t *lsubk, uint8_t* rsubk, +BD_PRIVATE int crypto_aes128e(const uint8_t *key, const uint8_t *data, uint8_t *dst); +BD_PRIVATE int crypto_aes128d(const uint8_t *key, const uint8_t *data, uint8_t *dst); +BD_PRIVATE int crypto_aesg3(const uint8_t *D, uint8_t *lsubk, uint8_t* rsubk, uint8_t *pk); // returns left, centre, right keys -BD_PRIVATE void crypto_aes_cmac_16(const unsigned char *data, const unsigned char *aes_key, unsigned char *cmac); +BD_PRIVATE int crypto_aes_cmac_16(const unsigned char *data, const unsigned char *aes_key, unsigned char *cmac); -BD_PRIVATE void crypto_aacs_decrypt(const uint8_t *key, uint8_t *out, size_t out_size, const uint8_t *in, size_t in_size); +BD_PRIVATE int crypto_aacs_decrypt(const uint8_t *key, uint8_t *out, size_t out_size, const uint8_t *in, size_t in_size); BD_PRIVATE void crypto_aacs_sign(const uint8_t *cert, const uint8_t *priv_key, uint8_t *signature, ===================================== src/libaacs/mkb.c ===================================== @@ -41,10 +41,6 @@ static const uint8_t *_record(MKB *mkb, uint8_t type, size_t *rec_len) while (pos + 4 <= mkb->size) { len = MKINT_BE24(mkb->buf + pos + 1); - if (rec_len) { - *rec_len = len; - } - if (mkb->buf[pos] == type) { BD_DEBUG(DBG_MKB, "Retrieved MKB record 0x%02x (%p)\n", type, (void*)(mkb->buf + pos)); @@ -55,6 +51,10 @@ static const uint8_t *_record(MKB *mkb, uint8_t type, size_t *rec_len) return NULL; } + if (rec_len) { + *rec_len = len; + } + return mkb->buf + pos; } ===================================== src/libaacs/mmc.c ===================================== @@ -539,6 +539,7 @@ static int _read_vid(MMC *mmc, uint8_t agid, const uint8_t *bus_key, uint8_t *vi { uint8_t mac[16], calc_mac[16]; char str[512]; + int err; BD_DEBUG(DBG_MMC, "Reading VID from drive...\n"); @@ -549,7 +550,10 @@ static int _read_vid(MMC *mmc, uint8_t agid, const uint8_t *bus_key, uint8_t *vi } /* verify MAC */ - crypto_aes_cmac_16(vid, bus_key, calc_mac); + err = crypto_aes_cmac_16(vid, bus_key, calc_mac); + if (err) { + LOG_CRYPTO_ERROR(DBG_MMC, "VID MAC calculation failed", err); + } if (memcmp(calc_mac, mac, 16)) { BD_DEBUG(DBG_MMC | DBG_CRIT, "VID MAC is incorrect. This means this Volume ID is not correct.\n"); } @@ -566,6 +570,7 @@ static int _read_pmsn(MMC *mmc, uint8_t agid, const uint8_t *bus_key, uint8_t *p { uint8_t mac[16], calc_mac[16]; char str[512]; + int err; BD_DEBUG(DBG_MMC, "Reading PMSN from drive...\n"); @@ -576,7 +581,10 @@ static int _read_pmsn(MMC *mmc, uint8_t agid, const uint8_t *bus_key, uint8_t *p } /* verify MAC */ - crypto_aes_cmac_16(pmsn, bus_key, calc_mac); + err = crypto_aes_cmac_16(pmsn, bus_key, calc_mac); + if (err) { + LOG_CRYPTO_ERROR(DBG_MMC, "PMSN MAC calculation failed", err); + } if (memcmp(calc_mac, mac, 16)) { BD_DEBUG(DBG_MMC | DBG_CRIT, "PMSN MAC is incorrect. This means this Pre-recorded Medial Serial Number is not correct.\n"); } @@ -599,13 +607,19 @@ static int _read_data_keys(MMC *mmc, uint8_t agid, const uint8_t *bus_key, if (_mmc_read_data_keys(mmc, agid, encrypted_read_data_key, encrypted_write_data_key)) { if (read_data_key) { - crypto_aes128d(bus_key, encrypted_read_data_key, read_data_key); + int err = crypto_aes128d(bus_key, encrypted_read_data_key, read_data_key); + if (err) { + LOG_CRYPTO_ERROR(DBG_MMC, "decrypting read data key failed", err); + } if (DEBUG_KEYS) { BD_DEBUG(DBG_MMC, "READ DATA KEY : %s\n", str_print_hex(str, read_data_key, 16)); } } if (write_data_key) { - crypto_aes128d(bus_key, encrypted_write_data_key, write_data_key); + int err = crypto_aes128d(bus_key, encrypted_write_data_key, write_data_key); + if (err) { + LOG_CRYPTO_ERROR(DBG_MMC, "decrypting write data key failed", err); + } if (DEBUG_KEYS) { BD_DEBUG(DBG_MMC, "WRITE DATA KEY : %s\n", str_print_hex(str, write_data_key, 16)); } View it on GitLab: https://code.videolan.org/videolan/libaacs/-/compare/7cee1c2ac1b0326f4bab3d756b53c5a0ab900002...de0f0c84a41d9e3e12e3e3a49c4e11cb6a0d7dcc -- View it on GitLab: https://code.videolan.org/videolan/libaacs/-/compare/7cee1c2ac1b0326f4bab3d756b53c5a0ab900002...de0f0c84a41d9e3e12e3e3a49c4e11cb6a0d7dcc You're receiving this email because of your account on code.videolan.org.
_______________________________________________ libaacs-devel mailing list libaacs-devel@videolan.org https://mailman.videolan.org/listinfo/libaacs-devel