diff --git a/libwvdrmengine/oemcrypto/mock/src/oem_cert.cpp b/libwvdrmengine/oemcrypto/mock/src/oem_cert.cpp new file mode 100644 index 00000000..8e111f82 --- /dev/null +++ b/libwvdrmengine/oemcrypto/mock/src/oem_cert.cpp @@ -0,0 +1,141 @@ +// This file contains the test OEM cert. + +#include "oem_cert.h" + +// TODO(fredgc, b/30141311): get a real certificate from server gang. +// TODO(fredgc): This is in PEM format. Is that what we want? +const uint8_t kOEMPublicCert[] = "-----BEGIN CERTIFICATE-----\n" + "MIIEOTCCAyGgAwIBAgIJAJNm87hSM9ZIMA0GCSqGSIb3DQEBCwUAMIGyMQswCQYD\n" + "VQQGEwJVUzETMBEGA1UECAwKV2FzaGluZ3RvbjERMA8GA1UEBwwIS2lya2xhbmQx\n" + "GDAWBgNVBAoMD0dvb2dsZSBXaWRldmluZTEXMBUGA1UECwwOVGVzdCBhbmQgRGVi\n" + "dWcxJjAkBgNVBAMMHU9FTUNyeXB0byBNb2NrIFJlZmVyZW5jZSBDb2RlMSAwHgYJ\n" + "KoZIhvcNAQkBFhFmcmVkZ2NAZ29vZ2xlLmNvbTAeFw0xNjEwMDYxODUzNDZaFw0x\n" + "NjEwMTYxODUzNDZaMIGyMQswCQYDVQQGEwJVUzETMBEGA1UECAwKV2FzaGluZ3Rv\n" + "bjERMA8GA1UEBwwIS2lya2xhbmQxGDAWBgNVBAoMD0dvb2dsZSBXaWRldmluZTEX\n" + "MBUGA1UECwwOVGVzdCBhbmQgRGVidWcxJjAkBgNVBAMMHU9FTUNyeXB0byBNb2Nr\n" + "IFJlZmVyZW5jZSBDb2RlMSAwHgYJKoZIhvcNAQkBFhFmcmVkZ2NAZ29vZ2xlLmNv\n" + "bTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMuQQOqS9Q6K/Di8G4xl\n" + "8pz6Ea90D1FLYzIZXd98Ybd94qwWHYaaNuTfTXvZH07fWxrc8HG44N51ArzZGEaT\n" + "h1O7Jt39qLGMirocCgQLxNI3SP7l/pXmsZBM20tYKOoSq7E68eFbXWp39LDOVElS\n" + "/Lib0QkcwmJd55Fnxk6PIscBqYQilLIglQheoDLcljmOd9Rcr59JTtDENfBJE+SC\n" + "ZD0Kckc2e6lBvy/VGKUqE2hmt00pFBugWsN+SkasLGst5/pTVZfTKOBd1E3OvfL3\n" + "qtli4bRyPVX23zSk/bCzxQO47pXe6nVna9m4Yk/LfwJfDIb+r1ErNwyZ4SmZLw6T\n" + "LrkCAwEAAaNQME4wHQYDVR0OBBYEFNx/l/kMs1AY9IhIphtjzR7cwIVBMB8GA1Ud\n" + "IwQYMBaAFNx/l/kMs1AY9IhIphtjzR7cwIVBMAwGA1UdEwQFMAMBAf8wDQYJKoZI\n" + "hvcNAQELBQADggEBAFSaXoWtFU/895lD1Sh/u6pdJcGuCJS0/s2scs95T1sglpfn\n" + "7pdTNtC1aniGuN0T+Aa2O95rJnS0W6RBGdKt1umFOcC7NfRBq1h7a1rn5wYicE5z\n" + "6rIumCSU4oniKMnQ5J+6LpKUFDVJt2W2o8LCKrHWgvcomo8B4ffdKrg+IKpS9Lxc\n" + "U3wyi27rRCyH004YpyE48hPXB3et6OmP2/Aw01d9LxTXieDh0HkhptEllV5EyGM2\n" + "nnRkbd21nHMkVUDzXYWDibxQj6PXw57smnjx7vTiZ1GoE72g2ENSwT1MQhoI59hy\n" + "WCKO91GNxZnyblSTrjLvzAY2hlVCauo7NmLG/yM=\n" + "-----END CERTIFICATE-----\n"; + +const size_t kOEMPublicCertSize = sizeof(kOEMPublicCert); + +// TODO(fredgc): get the private key that goes with the certificat above. +const uint8_t kOEMPrivateKey[] = { + 0x30, 0x82, 0x04, 0xbd, 0x02, 0x01, 0x00, 0x30, 0x0d, 0x06, 0x09, 0x2a, + 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82, + 0x04, 0xa7, 0x30, 0x82, 0x04, 0xa3, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, + 0x01, 0x00, 0xcb, 0x90, 0x40, 0xea, 0x92, 0xf5, 0x0e, 0x8a, 0xfc, 0x38, + 0xbc, 0x1b, 0x8c, 0x65, 0xf2, 0x9c, 0xfa, 0x11, 0xaf, 0x74, 0x0f, 0x51, + 0x4b, 0x63, 0x32, 0x19, 0x5d, 0xdf, 0x7c, 0x61, 0xb7, 0x7d, 0xe2, 0xac, + 0x16, 0x1d, 0x86, 0x9a, 0x36, 0xe4, 0xdf, 0x4d, 0x7b, 0xd9, 0x1f, 0x4e, + 0xdf, 0x5b, 0x1a, 0xdc, 0xf0, 0x71, 0xb8, 0xe0, 0xde, 0x75, 0x02, 0xbc, + 0xd9, 0x18, 0x46, 0x93, 0x87, 0x53, 0xbb, 0x26, 0xdd, 0xfd, 0xa8, 0xb1, + 0x8c, 0x8a, 0xba, 0x1c, 0x0a, 0x04, 0x0b, 0xc4, 0xd2, 0x37, 0x48, 0xfe, + 0xe5, 0xfe, 0x95, 0xe6, 0xb1, 0x90, 0x4c, 0xdb, 0x4b, 0x58, 0x28, 0xea, + 0x12, 0xab, 0xb1, 0x3a, 0xf1, 0xe1, 0x5b, 0x5d, 0x6a, 0x77, 0xf4, 0xb0, + 0xce, 0x54, 0x49, 0x52, 0xfc, 0xb8, 0x9b, 0xd1, 0x09, 0x1c, 0xc2, 0x62, + 0x5d, 0xe7, 0x91, 0x67, 0xc6, 0x4e, 0x8f, 0x22, 0xc7, 0x01, 0xa9, 0x84, + 0x22, 0x94, 0xb2, 0x20, 0x95, 0x08, 0x5e, 0xa0, 0x32, 0xdc, 0x96, 0x39, + 0x8e, 0x77, 0xd4, 0x5c, 0xaf, 0x9f, 0x49, 0x4e, 0xd0, 0xc4, 0x35, 0xf0, + 0x49, 0x13, 0xe4, 0x82, 0x64, 0x3d, 0x0a, 0x72, 0x47, 0x36, 0x7b, 0xa9, + 0x41, 0xbf, 0x2f, 0xd5, 0x18, 0xa5, 0x2a, 0x13, 0x68, 0x66, 0xb7, 0x4d, + 0x29, 0x14, 0x1b, 0xa0, 0x5a, 0xc3, 0x7e, 0x4a, 0x46, 0xac, 0x2c, 0x6b, + 0x2d, 0xe7, 0xfa, 0x53, 0x55, 0x97, 0xd3, 0x28, 0xe0, 0x5d, 0xd4, 0x4d, + 0xce, 0xbd, 0xf2, 0xf7, 0xaa, 0xd9, 0x62, 0xe1, 0xb4, 0x72, 0x3d, 0x55, + 0xf6, 0xdf, 0x34, 0xa4, 0xfd, 0xb0, 0xb3, 0xc5, 0x03, 0xb8, 0xee, 0x95, + 0xde, 0xea, 0x75, 0x67, 0x6b, 0xd9, 0xb8, 0x62, 0x4f, 0xcb, 0x7f, 0x02, + 0x5f, 0x0c, 0x86, 0xfe, 0xaf, 0x51, 0x2b, 0x37, 0x0c, 0x99, 0xe1, 0x29, + 0x99, 0x2f, 0x0e, 0x93, 0x2e, 0xb9, 0x02, 0x03, 0x01, 0x00, 0x01, 0x02, + 0x82, 0x01, 0x00, 0x5d, 0xc7, 0x67, 0x20, 0xa9, 0xf3, 0x1b, 0x70, 0x0c, + 0x22, 0x57, 0x06, 0x99, 0xf7, 0x9d, 0x7d, 0x93, 0xf6, 0xf1, 0xcd, 0x96, + 0x00, 0xed, 0xaa, 0x15, 0x3a, 0x7a, 0x74, 0xaa, 0xe8, 0x99, 0x8f, 0xf5, + 0x0d, 0x32, 0x63, 0x07, 0xcf, 0xa3, 0xda, 0x6c, 0xc5, 0x55, 0x79, 0x01, + 0x63, 0x64, 0xa2, 0xa4, 0x0d, 0x84, 0xf7, 0xdf, 0x24, 0x39, 0x57, 0xce, + 0x9b, 0x11, 0xa8, 0x8d, 0x5b, 0x09, 0xcd, 0x19, 0x3b, 0x1e, 0xa9, 0xed, + 0x3d, 0x5e, 0x71, 0xca, 0xab, 0x80, 0x31, 0xbc, 0xfa, 0x3f, 0x9e, 0x18, + 0x92, 0xd5, 0x82, 0x23, 0xac, 0xd3, 0xc0, 0x96, 0xa7, 0xb0, 0x5e, 0x3c, + 0xfb, 0x18, 0xfe, 0xdf, 0xf7, 0x37, 0xd7, 0x8a, 0x2f, 0xcf, 0x0c, 0xd4, + 0x3d, 0x5f, 0xd0, 0x94, 0xb7, 0x16, 0x96, 0x35, 0xb2, 0x67, 0x70, 0x48, + 0x5c, 0xe8, 0xc5, 0xf5, 0xc6, 0xc9, 0x25, 0x07, 0xec, 0x0d, 0xa1, 0x74, + 0x09, 0x9d, 0xcd, 0x25, 0xa5, 0x7a, 0x2f, 0xa6, 0x4c, 0xba, 0x7d, 0x55, + 0x4f, 0x79, 0x83, 0xaa, 0xfa, 0x3a, 0xc0, 0xaf, 0xc2, 0x33, 0xb2, 0x9a, + 0x68, 0x89, 0x72, 0x2f, 0x86, 0x69, 0x28, 0x1b, 0xdc, 0xa2, 0x05, 0xe3, + 0xfc, 0x24, 0x4c, 0xe0, 0x02, 0xb7, 0x06, 0x4b, 0xe0, 0x88, 0xe9, 0x79, + 0x72, 0x46, 0x1c, 0x49, 0x5e, 0xfa, 0x2d, 0x29, 0xe5, 0xbf, 0x29, 0xfe, + 0xf2, 0xee, 0xeb, 0xe8, 0x4a, 0x8d, 0xdd, 0xfa, 0x8e, 0xb0, 0x65, 0x68, + 0x38, 0xa5, 0xb4, 0xd7, 0x75, 0xd7, 0x8c, 0x32, 0x51, 0xe3, 0x97, 0x00, + 0x91, 0x19, 0x87, 0xaa, 0xeb, 0x4b, 0xcf, 0xf9, 0x6b, 0xf2, 0x87, 0xb9, + 0x93, 0x4e, 0xd7, 0x5c, 0x27, 0xbb, 0x92, 0x29, 0x5e, 0xb8, 0xe9, 0x75, + 0xc0, 0xc6, 0xa3, 0x8a, 0xb7, 0x1e, 0x19, 0xce, 0xd9, 0x5a, 0xc1, 0x0f, + 0x6d, 0xa6, 0x4a, 0x56, 0x24, 0x10, 0x01, 0x02, 0x81, 0x81, 0x00, 0xe8, + 0x1b, 0x99, 0x55, 0x0e, 0x19, 0x8b, 0x48, 0x46, 0xb1, 0x36, 0xb0, 0xe8, + 0x15, 0x5f, 0x45, 0x8b, 0x09, 0xac, 0x82, 0xd1, 0x93, 0x6f, 0x8d, 0xed, + 0xe8, 0x80, 0x82, 0xe4, 0xbc, 0x33, 0x40, 0x50, 0x71, 0x3f, 0x2c, 0x20, + 0x46, 0x34, 0x3f, 0x27, 0xc3, 0x98, 0x66, 0x34, 0x99, 0x05, 0x06, 0x53, + 0x43, 0xdf, 0x52, 0x0b, 0x56, 0x1a, 0xde, 0x3f, 0xbf, 0xba, 0x61, 0xd3, + 0xcf, 0xfd, 0xee, 0x34, 0x71, 0x75, 0x9f, 0xfd, 0xc4, 0xb0, 0x8b, 0x26, + 0xb1, 0x77, 0x83, 0xd4, 0x90, 0x28, 0xc2, 0xb7, 0x52, 0x98, 0xa0, 0x6b, + 0x4b, 0x19, 0x8b, 0x28, 0xbb, 0x18, 0x3e, 0x29, 0x14, 0x7e, 0xa3, 0x87, + 0xf8, 0x4d, 0x8a, 0x67, 0x3a, 0xf6, 0xec, 0x04, 0x7b, 0xfb, 0x3e, 0xa5, + 0xe3, 0xbb, 0xb2, 0x35, 0xf2, 0xd1, 0x63, 0x55, 0xb6, 0x87, 0x07, 0xea, + 0xbb, 0x06, 0x62, 0xbf, 0xaa, 0xbb, 0x19, 0x02, 0x81, 0x81, 0x00, 0xe0, + 0x84, 0x77, 0xb0, 0xc1, 0x94, 0x89, 0xc6, 0x54, 0x78, 0x8a, 0xf0, 0xcd, + 0xa4, 0x88, 0x92, 0xb4, 0xc9, 0xf1, 0x1c, 0x60, 0xea, 0x6d, 0x1c, 0x1d, + 0x33, 0x92, 0x12, 0xe3, 0xe3, 0xd4, 0x11, 0xb6, 0x4d, 0x05, 0x93, 0xbc, + 0x19, 0x50, 0xfc, 0x20, 0xe6, 0x07, 0x4a, 0xbc, 0xb6, 0x4f, 0xc1, 0x81, + 0xc8, 0x71, 0xa7, 0xe2, 0x79, 0xb3, 0xc9, 0x43, 0x43, 0xca, 0x27, 0xe7, + 0x37, 0x5b, 0x20, 0x83, 0x14, 0x8f, 0xb7, 0xba, 0x6c, 0x19, 0x21, 0xd5, + 0x60, 0x87, 0xae, 0x45, 0xa8, 0x17, 0xd8, 0x73, 0xae, 0x65, 0xae, 0x83, + 0x26, 0xff, 0x4e, 0x4f, 0x95, 0xdc, 0xce, 0x12, 0x40, 0xe6, 0xdd, 0xf2, + 0x64, 0x84, 0x65, 0x86, 0x3e, 0xb4, 0xbe, 0x2d, 0x95, 0x74, 0x5c, 0xb2, + 0xc6, 0x7c, 0x84, 0x17, 0x06, 0xe8, 0x80, 0xc8, 0xfe, 0x79, 0x22, 0xe6, + 0xfa, 0x1f, 0xd2, 0x71, 0x84, 0x24, 0xa1, 0x02, 0x81, 0x80, 0x1d, 0x33, + 0x63, 0xad, 0xfc, 0xb1, 0x20, 0x01, 0xbe, 0xcb, 0x0a, 0xbb, 0x64, 0xe7, + 0x53, 0x6e, 0x17, 0x58, 0xe7, 0x38, 0x2a, 0x0f, 0xa7, 0x68, 0x2e, 0xb7, + 0x22, 0x7b, 0xd5, 0x35, 0x0c, 0x29, 0x9a, 0x35, 0x35, 0x22, 0x63, 0x09, + 0x12, 0x07, 0xa4, 0x04, 0x0a, 0x87, 0x49, 0x34, 0xbb, 0x1a, 0x19, 0x9d, + 0x9f, 0x59, 0xde, 0x0d, 0x3e, 0x22, 0x19, 0xd9, 0x10, 0x24, 0xc0, 0x96, + 0x19, 0x37, 0x3f, 0xa7, 0xca, 0x89, 0x8f, 0x4e, 0x90, 0x7b, 0x61, 0x29, + 0xd0, 0x84, 0x68, 0x58, 0x9e, 0x98, 0x28, 0xa2, 0x1e, 0x8b, 0x88, 0x14, + 0x11, 0xa9, 0x9d, 0x3d, 0x34, 0x86, 0x95, 0x7a, 0x7b, 0x98, 0x2d, 0x42, + 0x02, 0xd7, 0x57, 0xb7, 0x66, 0x5b, 0x39, 0x11, 0x34, 0x01, 0xa4, 0xb3, + 0x2a, 0xe8, 0xf7, 0xba, 0x8d, 0xb7, 0x36, 0x90, 0x59, 0x1a, 0x98, 0xe0, + 0x60, 0xa4, 0x49, 0xc2, 0xbb, 0xf9, 0x02, 0x81, 0x80, 0x06, 0x01, 0x65, + 0x16, 0x34, 0x47, 0x5d, 0xdc, 0x11, 0x3c, 0x5c, 0x33, 0x0e, 0xbd, 0x1c, + 0xee, 0x17, 0xa9, 0xe3, 0x2a, 0x28, 0x29, 0x7d, 0x1b, 0xa8, 0x68, 0x4d, + 0xba, 0xf5, 0x9f, 0x8d, 0x77, 0x9f, 0xd1, 0xb5, 0x99, 0x7b, 0x09, 0x8e, + 0x52, 0x00, 0x2b, 0x46, 0xfc, 0xa7, 0xc9, 0x94, 0x9e, 0x8f, 0x73, 0x26, + 0x1f, 0x20, 0x7e, 0xb2, 0xe1, 0x6a, 0x4c, 0x30, 0xe7, 0x1a, 0x57, 0x2f, + 0xb7, 0xd1, 0xe9, 0xc5, 0xe2, 0x5b, 0x39, 0x32, 0xfe, 0xe5, 0xaf, 0x3c, + 0x51, 0xdc, 0x09, 0x20, 0x02, 0x29, 0x2d, 0xfc, 0x08, 0x4b, 0xf7, 0xca, + 0x12, 0x75, 0x2c, 0x84, 0x08, 0x7b, 0x12, 0x83, 0x5a, 0x62, 0x76, 0x6f, + 0xd8, 0x2b, 0x5c, 0x18, 0x07, 0x92, 0x3e, 0x92, 0x2b, 0x3c, 0x98, 0xf4, + 0x91, 0xaf, 0xef, 0xfe, 0x5e, 0x1b, 0x82, 0x3b, 0x09, 0x44, 0xf6, 0x61, + 0xcd, 0x86, 0x3d, 0xcb, 0xa1, 0x02, 0x81, 0x81, 0x00, 0xe5, 0x81, 0xf6, + 0x6f, 0x37, 0xf4, 0xef, 0xc7, 0x0e, 0xdf, 0x39, 0xd0, 0x97, 0x68, 0x1c, + 0xd5, 0x12, 0x42, 0x00, 0x0e, 0xd1, 0x89, 0xdc, 0xf5, 0x24, 0x30, 0xb3, + 0xeb, 0xea, 0x64, 0x3c, 0x9e, 0xa2, 0xc3, 0x49, 0x3c, 0xed, 0x2d, 0x4e, + 0x9a, 0x00, 0x23, 0x71, 0xcc, 0x15, 0xda, 0x49, 0xdc, 0xab, 0xd1, 0x36, + 0xe1, 0x8c, 0x91, 0x6c, 0x5b, 0x47, 0x43, 0x34, 0xec, 0xcd, 0x0c, 0xd0, + 0x88, 0x7c, 0x5a, 0xd4, 0x91, 0x79, 0xe5, 0xe6, 0xd2, 0x5d, 0x2e, 0x14, + 0x26, 0x81, 0x94, 0x9f, 0x29, 0x2b, 0x3e, 0xd6, 0x2f, 0x2d, 0xd9, 0xec, + 0x88, 0x6a, 0xd3, 0x35, 0x71, 0x8a, 0xb2, 0xef, 0x22, 0xdc, 0xab, 0x26, + 0xf9, 0x4d, 0x4c, 0x08, 0x8e, 0x16, 0x5b, 0x56, 0xb6, 0x76, 0x61, 0x89, + 0x8a, 0x3a, 0xdb, 0xbb, 0x42, 0xe3, 0x50, 0x3f, 0xa1, 0x08, 0x82, 0xc2, + 0x92, 0xef, 0x8c, 0xc2, 0xca +}; + +const size_t kOEMPrivateKeySize = sizeof(kOEMPrivateKey); diff --git a/libwvdrmengine/oemcrypto/mock/src/oem_cert.h b/libwvdrmengine/oemcrypto/mock/src/oem_cert.h new file mode 100644 index 00000000..8dd846c2 --- /dev/null +++ b/libwvdrmengine/oemcrypto/mock/src/oem_cert.h @@ -0,0 +1,14 @@ +// This header is used to access the OEM certificate if one is in use. +#ifndef OEM_CERT_H_ +#define OEM_CERT_H_ + +#include +#include + +extern const uint8_t kOEMPrivateKey[]; +extern const size_t kOEMPrivateKeySize; + +extern const uint8_t kOEMPublicCert[]; +extern const size_t kOEMPublicCertSize; + +#endif // OEM_CERT_H_ diff --git a/libwvdrmengine/oemcrypto/mock/src/oemcrypto_engine_device_properties.cpp b/libwvdrmengine/oemcrypto/mock/src/oemcrypto_engine_device_properties.cpp index 7965ab64..6f9c67db 100644 --- a/libwvdrmengine/oemcrypto/mock/src/oemcrypto_engine_device_properties.cpp +++ b/libwvdrmengine/oemcrypto/mock/src/oemcrypto_engine_device_properties.cpp @@ -38,6 +38,17 @@ bool CryptoEngine::supports_keybox() { return true; } +// This version uses a keybox. +OEMCrypto_ProvisioningMethod CryptoEngine::provisioning_method() { + return OEMCrypto_Keybox; +} + +OEMCryptoResult CryptoEngine::get_oem_certificate(SessionContext *session, + uint8_t *public_cert, + size_t *public_cert_length) { + return OEMCrypto_ERROR_NOT_IMPLEMENTED; +} + // Returns false for mock library to indicate the client does not support // anti-rollback hardware. bool CryptoEngine::is_anti_rollback_hw_present() { diff --git a/libwvdrmengine/oemcrypto/mock/src/oemcrypto_engine_device_properties_L1.cpp b/libwvdrmengine/oemcrypto/mock/src/oemcrypto_engine_device_properties_L1.cpp index 62db4319..5ffc068a 100644 --- a/libwvdrmengine/oemcrypto/mock/src/oemcrypto_engine_device_properties_L1.cpp +++ b/libwvdrmengine/oemcrypto/mock/src/oemcrypto_engine_device_properties_L1.cpp @@ -40,6 +40,17 @@ bool CryptoEngine::supports_keybox() { return true; } +// This version uses a keybox. +OEMCrypto_ProvisioningMethod CryptoEngine::provisioning_method() { + return OEMCrypto_Keybox; +} + +OEMCryptoResult CryptoEngine::get_oem_certificate(SessionContext *session, + uint8_t *public_cert, + size_t *public_cert_length) { + return OEMCrypto_ERROR_NOT_IMPLEMENTED; +} + // Returns true to indicate the client does support anti-rollback hardware. bool CryptoEngine::is_anti_rollback_hw_present() { return true; diff --git a/libwvdrmengine/oemcrypto/mock/src/oemcrypto_engine_device_properties_cert.cpp b/libwvdrmengine/oemcrypto/mock/src/oemcrypto_engine_device_properties_cert.cpp index 352e2eeb..2a4dec2b 100644 --- a/libwvdrmengine/oemcrypto/mock/src/oemcrypto_engine_device_properties_cert.cpp +++ b/libwvdrmengine/oemcrypto/mock/src/oemcrypto_engine_device_properties_cert.cpp @@ -41,6 +41,17 @@ bool CryptoEngine::supports_keybox() { return false; } +// This version uses a baked in DRM certificate. +OEMCrypto_ProvisioningMethod CryptoEngine::provisioning_method() { + return OEMCrypto_DrmCertificate; +} + +OEMCryptoResult CryptoEngine::get_oem_certificate(SessionContext *session, + uint8_t *public_cert, + size_t *public_cert_length) { + return OEMCrypto_ERROR_NOT_IMPLEMENTED; +} + // Returns true to indicate the client does support anti-rollback hardware. bool CryptoEngine::is_anti_rollback_hw_present() { return false; diff --git a/libwvdrmengine/oemcrypto/mock/src/oemcrypto_engine_device_properties_prov30.cpp b/libwvdrmengine/oemcrypto/mock/src/oemcrypto_engine_device_properties_prov30.cpp new file mode 100644 index 00000000..1d783f80 --- /dev/null +++ b/libwvdrmengine/oemcrypto/mock/src/oemcrypto_engine_device_properties_prov30.cpp @@ -0,0 +1,97 @@ +// Copyright 2016 Google Inc. All Rights Reserved. +// +// Mock implementation of OEMCrypto APIs +// +// This file contains oemcrypto engine properties that would be for a +// level 2 device that does not have persistant storage or a keybox. +// Note: this is for illustration only. Production devices are rarely level 2. +#include "oemcrypto_engine_mock.h" + +#include + +#include "log.h" +#include "oem_cert.h" + +namespace wvoec_mock { + +// If local_display() returns true, we pretend we are using a built-in display, +// instead of HDMI or WiFi output. +bool CryptoEngine::local_display() { + return true; +} + +// A closed platform is permitted to use clear buffers. +bool CryptoEngine::closed_platform() { + return false; +} + +// Returns the HDCP version currently in use. +OEMCrypto_HDCP_Capability CryptoEngine::current_hdcp_capability() { + return local_display() ? HDCP_NO_DIGITAL_OUTPUT : HDCP_V1; +} + +// Returns the max HDCP version supported. +OEMCrypto_HDCP_Capability CryptoEngine::maximum_hdcp_capability() { + return HDCP_NO_DIGITAL_OUTPUT; +} + +// Returns true if the client supports persistent storage of +// offline usage table information. +bool CryptoEngine::supports_storage() { + return false; +} + +// Returns true if the client uses a keybox as the root of trust. +bool CryptoEngine::supports_keybox() { + return false; +} + +// This version uses a keybox. +OEMCrypto_ProvisioningMethod CryptoEngine::provisioning_method() { + return OEMCrypto_OEMCertificate; +} + +OEMCryptoResult CryptoEngine::get_oem_certificate(SessionContext *session, + uint8_t *public_cert, + size_t *public_cert_length) { + if (kOEMPublicCertSize == 0) { + return OEMCrypto_ERROR_NOT_IMPLEMENTED; + } + if (public_cert_length == NULL) { + return OEMCrypto_ERROR_UNKNOWN_FAILURE; + } + if (*public_cert_length < kOEMPublicCertSize) { + *public_cert_length = kOEMPublicCertSize; + return OEMCrypto_ERROR_SHORT_BUFFER; + } + *public_cert_length = kOEMPublicCertSize; + if (public_cert == NULL) { + return OEMCrypto_ERROR_SHORT_BUFFER; + } + memcpy(public_cert, kOEMPublicCert, kOEMPublicCertSize); + if (!session->LoadRSAKey(kOEMPrivateKey, kOEMPrivateKeySize)) { + LOGE("Private RSA Key did not load correctly."); + return OEMCrypto_ERROR_INVALID_RSA_KEY; + } + return OEMCrypto_SUCCESS; +} + +// Returns true to indicate the client does support anti-rollback hardware. +bool CryptoEngine::is_anti_rollback_hw_present() { + return false; +} + +// Returns "L3" for a software only library. L1 is for hardware protected keys +// and data paths. L2 is for hardware protected keys but no data path +// protection. +const char* CryptoEngine::security_level() { + return "L2"; +} + +// This should start at 0, and be incremented only when a security patch has +// been applied to the device that fixes a security bug. +uint8_t CryptoEngine::security_patch_level() { + return 0; +} + +} // namespace wvoec_mock diff --git a/libwvdrmengine/oemcrypto/mock/src/oemcrypto_engine_mock.cpp b/libwvdrmengine/oemcrypto/mock/src/oemcrypto_engine_mock.cpp index 9d7ff559..e87bfe92 100644 --- a/libwvdrmengine/oemcrypto/mock/src/oemcrypto_engine_mock.cpp +++ b/libwvdrmengine/oemcrypto/mock/src/oemcrypto_engine_mock.cpp @@ -242,12 +242,71 @@ void SessionKeyTable::UpdateDuration(const KeyControlBlock& control) { } } +void RSA_shared_ptr::reset() { + if (rsa_key_ && key_owned_) { + RSA_free(rsa_key_); + } + key_owned_ = false; + rsa_key_ = NULL; +} + +bool RSA_shared_ptr::LoadPkcs8RsaKey(const uint8_t* buffer, size_t length) { + assert(buffer != NULL); + reset(); + key_owned_ = true; + uint8_t* pkcs8_rsa_key = const_cast(buffer); + BIO* bio = BIO_new_mem_buf(pkcs8_rsa_key, length); + if (bio == NULL) { + LOGE("[LoadPkcs8RsaKey(): Could not allocate bio buffer]"); + return false; + } + bool success = true; + PKCS8_PRIV_KEY_INFO* pkcs8_pki = d2i_PKCS8_PRIV_KEY_INFO_bio(bio, NULL); + if (pkcs8_pki == NULL) { + LOGE("[LoadPkcs8RsaKey(): d2i_PKCS8_PRIV_KEY_INFO_bio returned NULL]"); + success = false; + } + EVP_PKEY* evp = NULL; + if (success) { + evp = EVP_PKCS82PKEY(pkcs8_pki); + if (evp == NULL) { + LOGE("[LoadPkcs8RsaKey(): EVP_PKCS82PKEY returned NULL]"); + success = false; + } + } + if (success) { + rsa_key_ = EVP_PKEY_get1_RSA(evp); + if (rsa_key_ == NULL) { + LOGE("[LoadPkcs8RsaKey(): PrivateKeyInfo did not contain an RSA key]"); + success = false; + } + } + if (evp != NULL) { + EVP_PKEY_free(evp); + } + if (pkcs8_pki != NULL) { + PKCS8_PRIV_KEY_INFO_free(pkcs8_pki); + } + BIO_free(bio); + if (!success) { + return false; + } + switch (RSA_check_key(rsa_key_)) { + case 1: // valid. + return true; + case 0: // not valid. + LOGE("[LoadPkcs8RsaKey(): rsa key not valid]"); + dump_openssl_error(); + return false; + default: // -1 == check failed. + LOGE("[LoadPkcs8RsaKey(): error checking rsa key]"); + dump_openssl_error(); + return false; + } +} + SessionContext::~SessionContext() { if (usage_entry_) usage_entry_->set_session(NULL); - if (rsa_key_ && rsa_key_ != ce_->rsa_key()) { - RSA_free(rsa_key_); - rsa_key_ = NULL; - } } // Internal utility function to derive key using CMAC-128 @@ -339,20 +398,20 @@ bool SessionContext::DeriveKeys(const std::vector& master_key, bool SessionContext::RSADeriveKeys(const std::vector& enc_session_key, const std::vector& mac_key_context, const std::vector& enc_key_context) { - if (!rsa_key_) { + if (!rsa_key()) { LOGE("[RSADeriveKeys(): no RSA key set]"); return false; } - if (enc_session_key.size() != static_cast(RSA_size(rsa_key_))) { + if (enc_session_key.size() != static_cast(RSA_size(rsa_key()))) { LOGE("[RSADeriveKeys(): encrypted session key wrong size:%zu, expected %d]", - enc_session_key.size(), RSA_size(rsa_key_)); + enc_session_key.size(), RSA_size(rsa_key())); dump_openssl_error(); return false; } - session_key_.resize(RSA_size(rsa_key_)); + session_key_.resize(RSA_size(rsa_key())); int decrypted_size = RSA_private_decrypt(enc_session_key.size(), &enc_session_key[0], - &session_key_[0], rsa_key_, + &session_key_[0], rsa_key(), RSA_PKCS1_OAEP_PADDING); if (-1 == decrypted_size) { LOGE("[RSADeriveKeys(): error decrypting session key.]"); @@ -402,11 +461,11 @@ bool SessionContext::GenerateSignature(const uint8_t* message, } size_t SessionContext::RSASignatureSize() { - if (!rsa_key_) { + if (!rsa_key()) { LOGE("[GenerateRSASignature(): no RSA key set]"); return 0; } - return static_cast(RSA_size(rsa_key_)); + return static_cast(RSA_size(rsa_key())); } OEMCryptoResult SessionContext::GenerateRSASignature( @@ -417,19 +476,18 @@ OEMCryptoResult SessionContext::GenerateRSASignature( LOGE("[GenerateRSASignature(): OEMCrypto_ERROR_INVALID_CONTEXT]"); return OEMCrypto_ERROR_INVALID_CONTEXT; } - if (!rsa_key_) { + if (!rsa_key()) { LOGE("[GenerateRSASignature(): no RSA key set]"); return OEMCrypto_ERROR_INVALID_RSA_KEY; } - if (*signature_length < static_cast(RSA_size(rsa_key_))) { - *signature_length = RSA_size(rsa_key_); + if (*signature_length < static_cast(RSA_size(rsa_key()))) { + *signature_length = RSA_size(rsa_key()); return OEMCrypto_ERROR_SHORT_BUFFER; } if ((padding_scheme & allowed_schemes_) != padding_scheme) { LOGE("[GenerateRSASignature(): padding_scheme not allowed]"); return OEMCrypto_ERROR_INVALID_RSA_KEY; } - // This is the standard padding scheme used for license requests. if (padding_scheme == kSign_RSASSA_PSS) { // Hash the message using SHA1. @@ -442,7 +500,7 @@ OEMCryptoResult SessionContext::GenerateRSASignature( // Add PSS padding. std::vector padded_digest(*signature_length); - int status = RSA_padding_add_PKCS1_PSS_mgf1(rsa_key_, &padded_digest[0], + int status = RSA_padding_add_PKCS1_PSS_mgf1(rsa_key(), &padded_digest[0], hash, EVP_sha1(), NULL, kPssSaltLength); if (status == -1) { @@ -453,7 +511,7 @@ OEMCryptoResult SessionContext::GenerateRSASignature( // Encrypt PSS padded digest. status = RSA_private_encrypt(*signature_length, &padded_digest[0], signature, - rsa_key_, RSA_NO_PADDING); + rsa_key(), RSA_NO_PADDING); if (status == -1) { LOGE("[GeneratRSASignature(): error in private encrypt.]"); dump_openssl_error(); @@ -467,7 +525,7 @@ OEMCryptoResult SessionContext::GenerateRSASignature( } // Pad the message with PKCS1 padding, and then encrypt. size_t status = RSA_private_encrypt(message_length, message, signature, - rsa_key_, RSA_PKCS1_PADDING); + rsa_key(), RSA_PKCS1_PADDING); if (status != *signature_length) { LOGE("[GeneratRSASignature(): error in RSA private encrypt. status=%d]", status); dump_openssl_error(); @@ -711,6 +769,29 @@ bool SessionContext::InstallKey(const KeyId& key_id, return true; } +bool SessionContext::InstallRSAEncryptedKey(const uint8_t *encrypted_message_key, + size_t encrypted_message_key_length) { + encryption_key_.resize(RSA_size(rsa_key())); + int decrypted_size = RSA_private_decrypt( encrypted_message_key_length, + encrypted_message_key, + &encryption_key_[0], rsa_key(), + RSA_PKCS1_OAEP_PADDING); + if (-1 == decrypted_size) { + LOGE("[RSADeriveKeys(): error decrypting session key.]"); + dump_openssl_error(); + return false; + } + encryption_key_.resize(decrypted_size); + if (decrypted_size != static_cast(wvcdm::KEY_SIZE)) { + LOGE("[RSADeriveKeys(): error. session key is wrong size: %d.]", + decrypted_size); + dump_openssl_error(); + encryption_key_.clear(); + return false; + } + return true; +} + OEMCryptoResult SessionContext::RefreshKey( const KeyId& key_id, const std::vector& key_control, const std::vector& key_control_iv) { @@ -790,7 +871,7 @@ bool SessionContext::DecryptRSAKey(const uint8_t* enc_rsa_key, const uint8_t* enc_rsa_key_iv, uint8_t* pkcs8_rsa_key) { // Decrypt rsa key with keybox. - uint8_t iv_buffer[ wvcdm::KEY_IV_SIZE]; + uint8_t iv_buffer[wvcdm::KEY_IV_SIZE]; memcpy(iv_buffer, enc_rsa_key_iv, wvcdm::KEY_IV_SIZE); AES_KEY aes_key; AES_set_decrypt_key(&encryption_key_[0], 128, &aes_key); @@ -804,7 +885,7 @@ bool SessionContext::EncryptRSAKey(const uint8_t* pkcs8_rsa_key, const uint8_t* enc_rsa_key_iv, uint8_t* enc_rsa_key) { // Encrypt rsa key with keybox. - uint8_t iv_buffer[ wvcdm::KEY_IV_SIZE]; + uint8_t iv_buffer[wvcdm::KEY_IV_SIZE]; memcpy(iv_buffer, enc_rsa_key_iv, wvcdm::KEY_IV_SIZE); AES_KEY aes_key; AES_set_encrypt_key(&encryption_key_[0], 128, &aes_key); @@ -813,79 +894,22 @@ bool SessionContext::EncryptRSAKey(const uint8_t* pkcs8_rsa_key, return true; } -bool SessionContext::LoadRSAKey(uint8_t* pkcs8_rsa_key, - size_t rsa_key_length, - const uint8_t* message, - size_t message_length, - const uint8_t* signature, - size_t signature_length) { - // Validate message signature - if (!ValidateMessage(message, message_length, signature, signature_length)) { - LOGE("[LoadRSAKey(): Could not verify signature]"); - return false; - } - if (rsa_key_) { - RSA_free(rsa_key_); - rsa_key_ = NULL; - } +bool SessionContext::LoadRSAKey(const uint8_t* pkcs8_rsa_key, + size_t rsa_key_length) { + rsa_key_.reset(); if (rsa_key_length < 8) { LOGE("[LoadRSAKey(): Very Short Buffer]"); return false; } - if( (memcmp(pkcs8_rsa_key, "SIGN", 4) == 0) ) { - uint32_t *schemes_n = (uint32_t *)(pkcs8_rsa_key + 4); + if ((memcmp(pkcs8_rsa_key, "SIGN", 4) == 0)) { + uint32_t* schemes_n = (uint32_t*)(pkcs8_rsa_key + 4); allowed_schemes_ = htonl(*schemes_n); pkcs8_rsa_key += 8; rsa_key_length -= 8; + } else { + allowed_schemes_ = kSign_RSASSA_PSS; } - BIO *bio = BIO_new_mem_buf(pkcs8_rsa_key, rsa_key_length); - if ( bio == NULL ) { - LOGE("[LoadRSAKey(): Could not allocate bio buffer]"); - return false; - } - bool success = true; - PKCS8_PRIV_KEY_INFO *pkcs8_pki = d2i_PKCS8_PRIV_KEY_INFO_bio(bio, NULL); - if (pkcs8_pki == NULL) { - LOGE("d2i_PKCS8_PRIV_KEY_INFO_bio returned NULL."); - success = false; - } - EVP_PKEY *evp = NULL; - if (success) { - evp = EVP_PKCS82PKEY(pkcs8_pki); - if (evp == NULL) { - LOGE("EVP_PKCS82PKEY returned NULL."); - success = false; - } - } - if (success) { - rsa_key_ = EVP_PKEY_get1_RSA(evp); - if (rsa_key_ == NULL) { - LOGE("PrivateKeyInfo did not contain an RSA key."); - success = false; - } - } - if (evp != NULL) { - EVP_PKEY_free(evp); - } - if (pkcs8_pki != NULL) { - PKCS8_PRIV_KEY_INFO_free(pkcs8_pki); - } - BIO_free(bio); - if (!success) { - return false; - } - switch (RSA_check_key(rsa_key_)) { - case 1: // valid. - return true; - case 0: // not valid. - LOGE("[LoadRSAKey(): rsa key not valid]"); - dump_openssl_error(); - return false; - default: // -1 == check failed. - LOGE("[LoadRSAKey(): error checking rsa key]"); - dump_openssl_error(); - return false; - } + return rsa_key_.LoadPkcs8RsaKey(pkcs8_rsa_key, rsa_key_length); } OEMCryptoResult SessionContext::Generic_Encrypt(const uint8_t* in_buffer, @@ -921,11 +945,11 @@ OEMCryptoResult SessionContext::Generic_Encrypt(const uint8_t* in_buffer, return OEMCrypto_ERROR_UNKNOWN_FAILURE; } } - if ( algorithm != OEMCrypto_AES_CBC_128_NO_PADDING ) { + if (algorithm != OEMCrypto_AES_CBC_128_NO_PADDING) { LOGE("[Generic_Encrypt(): algorithm bad."); return OEMCrypto_ERROR_UNKNOWN_FAILURE; } - if ( buffer_length % AES_BLOCK_SIZE != 0 ) { + if (buffer_length % AES_BLOCK_SIZE != 0) { LOGE("[Generic_Encrypt(): buffers size bad."); return OEMCrypto_ERROR_UNKNOWN_FAILURE; } @@ -935,7 +959,7 @@ OEMCryptoResult SessionContext::Generic_Encrypt(const uint8_t* in_buffer, LOGE("[Generic_Encrypt(): FAILURE]"); return OEMCrypto_ERROR_UNKNOWN_FAILURE; } - uint8_t iv_buffer[ wvcdm::KEY_IV_SIZE]; + uint8_t iv_buffer[wvcdm::KEY_IV_SIZE]; memcpy(iv_buffer, iv, wvcdm::KEY_IV_SIZE); AES_cbc_encrypt(in_buffer, out_buffer, buffer_length, &aes_key, iv_buffer, AES_ENCRYPT); @@ -981,11 +1005,11 @@ OEMCryptoResult SessionContext::Generic_Decrypt(const uint8_t* in_buffer, return OEMCrypto_ERROR_UNKNOWN_FAILURE; } } - if ( algorithm != OEMCrypto_AES_CBC_128_NO_PADDING ) { + if (algorithm != OEMCrypto_AES_CBC_128_NO_PADDING) { LOGE("[Generic_Decrypt(): bad algorithm."); return OEMCrypto_ERROR_UNKNOWN_FAILURE; } - if ( buffer_length % AES_BLOCK_SIZE != 0 ) { + if (buffer_length % AES_BLOCK_SIZE != 0) { LOGE("[Generic_Decrypt(): bad buffer size."); return OEMCrypto_ERROR_UNKNOWN_FAILURE; } @@ -995,7 +1019,7 @@ OEMCryptoResult SessionContext::Generic_Decrypt(const uint8_t* in_buffer, LOGE("[Generic_Decrypt(): FAILURE]"); return OEMCrypto_ERROR_UNKNOWN_FAILURE; } - uint8_t iv_buffer[ wvcdm::KEY_IV_SIZE]; + uint8_t iv_buffer[wvcdm::KEY_IV_SIZE]; memcpy(iv_buffer, iv, wvcdm::KEY_IV_SIZE); AES_cbc_encrypt(in_buffer, out_buffer, buffer_length, &aes_key, iv_buffer, AES_DECRYPT); @@ -1039,7 +1063,7 @@ OEMCryptoResult SessionContext::Generic_Sign(const uint8_t* in_buffer, return OEMCrypto_ERROR_UNKNOWN_FAILURE; } } - if( algorithm != OEMCrypto_HMAC_SHA256 ) { + if (algorithm != OEMCrypto_HMAC_SHA256) { LOGE("[Generic_Sign(): bad algorithm."); return OEMCrypto_ERROR_UNKNOWN_FAILURE; } @@ -1089,7 +1113,7 @@ OEMCryptoResult SessionContext::Generic_Verify(const uint8_t* in_buffer, return OEMCrypto_ERROR_UNKNOWN_FAILURE; } } - if ( algorithm != OEMCrypto_HMAC_SHA256 ) { + if (algorithm != OEMCrypto_HMAC_SHA256) { LOGE("[Generic_Verify(): bad algorithm."); return OEMCrypto_ERROR_UNKNOWN_FAILURE; } @@ -1190,21 +1214,20 @@ bool SessionContext::IsUsageEntryValid() { void SessionContext::ReleaseUsageEntry() { usage_entry_ = NULL; } CryptoEngine::CryptoEngine(wvcdm::FileSystem* file_system) - : current_session_(NULL), - use_test_keybox_(false), + : use_test_keybox_(false), file_system_(file_system), - usage_table_(new UsageTable(this)), - rsa_key_(NULL) { + usage_table_(new UsageTable(this)) { ERR_load_crypto_strings(); - if (!supports_keybox() && !LoadPkcs8RsaKey(kPrivateKey, kPrivateKeySize)) { + if ((provisioning_method() == OEMCrypto_DrmCertificate) && + !rsa_key_.LoadPkcs8RsaKey(kPrivateKey, kPrivateKeySize)) { + // This error message is OK in unit tests which use test certificate. LOGE("FATAL ERROR: Platform uses a baked-in certificate instead of a " "keybox, but the certificate could not be loaded."); } } CryptoEngine::~CryptoEngine() { - current_session_ = NULL; sessions_.clear(); if (usage_table_) delete usage_table_; } @@ -1214,19 +1237,15 @@ void CryptoEngine::Terminate() {} KeyboxError CryptoEngine::ValidateKeybox() { return keybox().Validate(); } bool CryptoEngine::LoadTestRSAKey() { - if (rsa_key_) { - RSA_free(rsa_key_); - rsa_key_ = NULL; - } - return LoadPkcs8RsaKey(kTestRSAPKCS8PrivateKeyInfo2_2048, - sizeof(kTestRSAPKCS8PrivateKeyInfo2_2048)); + return rsa_key_.LoadPkcs8RsaKey(kTestRSAPKCS8PrivateKeyInfo2_2048, + sizeof(kTestRSAPKCS8PrivateKeyInfo2_2048)); } SessionId CryptoEngine::CreateSession() { wvcdm::AutoLock lock(session_table_lock_); static int unique_id = 1; SessionId sid = (SessionId)++unique_id; - SessionContext* sctx = new SessionContext(this, sid, this->rsa_key_); + SessionContext* sctx = new SessionContext(this, sid, rsa_key_); sessions_[sid] = sctx; return sid; } @@ -1252,59 +1271,6 @@ SessionContext* CryptoEngine::FindSession(SessionId sid) { return NULL; } -bool CryptoEngine::LoadPkcs8RsaKey(const uint8_t* buffer, size_t length) { - assert(buffer != NULL); - uint8_t* pkcs8_rsa_key = const_cast(buffer); - BIO* bio = BIO_new_mem_buf(pkcs8_rsa_key, length); - if (bio == NULL) { - LOGE("[LoadPkcs8RsaKey(): Could not allocate bio buffer]"); - return false; - } - bool success = true; - PKCS8_PRIV_KEY_INFO* pkcs8_pki = d2i_PKCS8_PRIV_KEY_INFO_bio(bio, NULL); - if (pkcs8_pki == NULL) { - LOGE("[LoadPkcs8RsaKey(): d2i_PKCS8_PRIV_KEY_INFO_bio returned NULL]"); - success = false; - } - EVP_PKEY* evp = NULL; - if (success) { - evp = EVP_PKCS82PKEY(pkcs8_pki); - if (evp == NULL) { - LOGE("[LoadPkcs8RsaKey(): EVP_PKCS82PKEY returned NULL]"); - success = false; - } - } - if (success) { - rsa_key_ = EVP_PKEY_get1_RSA(evp); - if (rsa_key_ == NULL) { - LOGE("[LoadPkcs8RsaKey(): PrivateKeyInfo did not contain an RSA key]"); - success = false; - } - } - if (evp != NULL) { - EVP_PKEY_free(evp); - } - if (pkcs8_pki != NULL) { - PKCS8_PRIV_KEY_INFO_free(pkcs8_pki); - } - BIO_free(bio); - if (!success) { - return false; - } - switch (RSA_check_key(rsa_key_)) { - case 1: // valid. - return true; - case 0: // not valid. - LOGE("[LoadPkcs8RsaKey(): rsa key not valid]"); - dump_openssl_error(); - return false; - default: // -1 == check failed. - LOGE("[LoadPkcs8RsaKey(): error checking rsa key]"); - dump_openssl_error(); - return false; - } -} - // Internal utility function to decrypt the message bool SessionContext::DecryptMessage(const std::vector& key, const std::vector& iv, diff --git a/libwvdrmengine/oemcrypto/mock/src/oemcrypto_engine_mock.h b/libwvdrmengine/oemcrypto/mock/src/oemcrypto_engine_mock.h index 1f263f0c..684a04d4 100644 --- a/libwvdrmengine/oemcrypto/mock/src/oemcrypto_engine_mock.h +++ b/libwvdrmengine/oemcrypto/mock/src/oemcrypto_engine_mock.h @@ -12,11 +12,11 @@ #include +#include "OEMCryptoCENC.h" // Needed for enums only. #include "file_store.h" #include "lock.h" #include "oemcrypto_key_mock.h" #include "oemcrypto_keybox_mock.h" -#include "OEMCryptoCENC.h" // Needed for enums only. #include "wv_cdm_types.h" namespace wvoec_mock { @@ -61,6 +61,7 @@ class NonceTable { void AddNonce(uint32_t nonce); bool CheckNonce(uint32_t nonce); void Flush(); + private: enum NonceTableState { kNTStateInvalid, @@ -72,12 +73,34 @@ class NonceTable { uint32_t nonces_[kTableSize]; }; +// Shared pointer with specialized destructor. This pointer is only shared +// from a CryptoEngine to a Session -- so we don't have to use full reference +// counting. +class RSA_shared_ptr { + public: + RSA_shared_ptr() : rsa_key_(NULL), key_owned_(false) {} + ~RSA_shared_ptr() { reset(); }; + // Explicitly allow copy as share. + explicit RSA_shared_ptr(const RSA_shared_ptr& other) : + rsa_key_(other.rsa_key_), key_owned_(false) {} + RSA* get() { return rsa_key_; } + void reset(); + bool LoadPkcs8RsaKey(const uint8_t* buffer, size_t length); + + private: + void operator=(const RSA_shared_ptr); // disallow assign. + + RSA* rsa_key_; + bool key_owned_; +}; + class SessionContext { private: SessionContext() {} public: - explicit SessionContext(CryptoEngine* ce, SessionId sid, RSA* rsa_key) + SessionContext(CryptoEngine* ce, SessionId sid, + const RSA_shared_ptr& rsa_key) : valid_(true), ce_(ce), id_(sid), @@ -132,7 +155,7 @@ class SessionContext { const uint8_t* signature, size_t signature_length); void StartTimer(); - uint32_t CurrentTimer(); // (seconds). + uint32_t CurrentTimer(); // (seconds). OEMCryptoResult LoadKeys(const uint8_t* message, size_t message_length, const uint8_t* signature, size_t signature_length, const uint8_t* enc_mac_key_iv, @@ -146,6 +169,8 @@ class SessionContext { const std::vector& key_control_iv, const std::vector& pst, bool ctr_mode); + bool InstallRSAEncryptedKey(const uint8_t *encrypted_message_key, + size_t encrypted_message_key_length); bool DecryptRSAKey(const uint8_t* enc_rsa_key, size_t enc_rsa_key_length, const uint8_t* wrapped_rsa_key_iv, @@ -154,12 +179,8 @@ class SessionContext { size_t enc_rsa_key_length, const uint8_t* enc_rsa_key_iv, uint8_t* enc_rsa_key); - bool LoadRSAKey(uint8_t* pkcs8_rsa_key, - size_t rsa_key_length, - const uint8_t* message, - size_t message_length, - const uint8_t* signature, - size_t signature_length); + bool LoadRSAKey(const uint8_t* pkcs8_rsa_key, + size_t rsa_key_length); OEMCryptoResult RefreshKey(const KeyId& key_id, const std::vector& key_control, const std::vector& key_control_iv); @@ -212,6 +233,8 @@ class SessionContext { size_t block_offset, const uint8_t* cipher_data, size_t cipher_data_length, uint8_t* clear_data); + RSA* rsa_key() { return rsa_key_.get(); } + bool valid_; CryptoEngine* ce_; SessionId id_; @@ -222,7 +245,7 @@ class SessionContext { const Key* current_content_key_; SessionKeyTable session_keys_; NonceTable nonce_table_; - RSA* rsa_key_; + RSA_shared_ptr rsa_key_; uint32_t allowed_schemes_; // for RSA signatures. time_t timer_start_; UsageTableEntry* usage_entry_; @@ -243,7 +266,7 @@ class CryptoEngine { WvKeybox& keybox() { return use_test_keybox_ ? test_keybox_ : keybox_; } WvKeybox& real_keybox() { return keybox_; } void UseTestKeybox() { use_test_keybox_ = true; } - RSA* rsa_key() { return rsa_key_; } + RSA* rsa_key() { return rsa_key_.get(); } bool LoadTestRSAKey(); SessionId CreateSession(); @@ -260,10 +283,6 @@ class CryptoEngine { return kMaxSupportedOEMCryptoSessions; } - void set_current_session_(SessionContext* current) { - current_session_ = current; - } - OEMCrypto_HDCP_Capability current_hdcp_capability(); OEMCrypto_HDCP_Capability maximum_hdcp_capability(); @@ -273,14 +292,15 @@ class CryptoEngine { bool closed_platform(); bool supports_storage(); bool supports_keybox(); + OEMCrypto_ProvisioningMethod provisioning_method(); + OEMCryptoResult get_oem_certificate(SessionContext* session, + uint8_t* public_cert, + size_t* public_cert_length); bool is_anti_rollback_hw_present(); const char* security_level(); uint8_t security_patch_level(); private: - bool LoadPkcs8RsaKey(const uint8_t* buffer, size_t length); - - SessionContext* current_session_; ActiveSessions sessions_; WvKeybox keybox_; WvTestKeybox test_keybox_; @@ -288,7 +308,7 @@ class CryptoEngine { wvcdm::Lock session_table_lock_; wvcdm::FileSystem* file_system_; UsageTable* usage_table_; - RSA* rsa_key_; // If no keybox, this is baked in certificate. + RSA_shared_ptr rsa_key_; // If no keybox, this is baked in certificate. CORE_DISALLOW_COPY_AND_ASSIGN(CryptoEngine); }; diff --git a/libwvdrmengine/oemcrypto/mock/src/oemcrypto_mock.cpp b/libwvdrmengine/oemcrypto/mock/src/oemcrypto_mock.cpp index a41dead1..b2908627 100644 --- a/libwvdrmengine/oemcrypto/mock/src/oemcrypto_mock.cpp +++ b/libwvdrmengine/oemcrypto/mock/src/oemcrypto_mock.cpp @@ -747,6 +747,45 @@ OEMCryptoResult OEMCrypto_IsKeyboxValid(void) { } } +extern "C" +OEMCrypto_ProvisioningMethod OEMCrypto_GetProvisioningMethod() { + if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) { + LOGI("-- OEMCrypto_ProvisioningMethod OEMCrypto_GetProvisioningMethod(void) {\n"); + } + if (!crypto_engine) { + LOGE("OEMCrypto_GetProvisioningMethod: OEMCrypto Not Initialized."); + return OEMCrypto_ProvisioningError; + } + return crypto_engine->provisioning_method(); +} + +extern "C" +OEMCryptoResult OEMCrypto_GetOEMPublicCertificate(OEMCrypto_SESSION session, + uint8_t *public_cert, + size_t *public_cert_length) { + if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) { + LOGI("-- OEMCryptoResult OEMCrypto_GetOEMPublicCertificate(%d) {\n", + session); + } + if (!crypto_engine) { + LOGE("OEMCrypto_GetOEMPublicCertificate: OEMCrypto Not Initialized."); + return OEMCrypto_ERROR_UNKNOWN_FAILURE; + } + if (crypto_engine->provisioning_method() != OEMCrypto_OEMCertificate) { + LOGE("OEMCrypto_GetOEMPublicCertificate: Provisioning method = %d.", + crypto_engine->provisioning_method() + ); + return OEMCrypto_ERROR_NOT_IMPLEMENTED; + } + SessionContext* session_ctx = crypto_engine->FindSession(session); + if (!session_ctx || !session_ctx->isValid()) { + LOGE("[OEMCrypto_GetOEMPublicCertificate(): ERROR_INVALID_SESSION]"); + return OEMCrypto_ERROR_INVALID_SESSION; + } + return crypto_engine->get_oem_certificate(session_ctx, + public_cert, public_cert_length); +} + extern "C" OEMCryptoResult OEMCrypto_GetDeviceID(uint8_t* deviceID, size_t* idLength) { @@ -831,6 +870,135 @@ OEMCryptoResult OEMCrypto_GetRandom(uint8_t* randomData, size_t dataLength) { return OEMCrypto_ERROR_UNKNOWN_FAILURE; } +extern "C" OEMCryptoResult OEMCrypto_RewrapDeviceRSAKey30( + OEMCrypto_SESSION session, const uint32_t* nonce, + const uint8_t* encrypted_message_key, size_t encrypted_message_key_length, + const uint8_t* enc_rsa_key, size_t enc_rsa_key_length, + const uint8_t* enc_rsa_key_iv, uint8_t* wrapped_rsa_key, + size_t* wrapped_rsa_key_length) { + if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls | kLoggingTraceNonce)) { + LOGI("-- OEMCryptoResult OEMCrypto_RewrapDeviceRSAKey30(%d)\n", session); + LOGI("nonce = %08X;\n", *nonce); + if (wvcdm::g_cutoff >= wvcdm::LOG_VERBOSE) { + dump_hex("encrypted_message_key", encrypted_message_key, + encrypted_message_key_length); + dump_hex("enc_rsa_key", enc_rsa_key, enc_rsa_key_length); + dump_hex("enc_rsa_key_iv", enc_rsa_key_iv, wvcdm::KEY_IV_SIZE); + } + } + if (!crypto_engine) { + LOGE("OEMCrypto_RewrapDeviceRSAKey30: OEMCrypto Not Initialized."); + return OEMCrypto_ERROR_UNKNOWN_FAILURE; + } + if (wrapped_rsa_key_length == NULL) { + LOGE("[OEMCrypto_RewrapDeviceRSAKey30(): OEMCrypto_ERROR_INVALID_CONTEXT]"); + return OEMCrypto_ERROR_INVALID_CONTEXT; + } + // For the reference implementation, the wrapped key and the encrypted + // key are the same size -- just encrypted with different keys. + // We add 32 bytes for a context, 32 for iv, and 32 bytes for a signature. + // Important: This layout must match OEMCrypto_LoadDeviceRSAKey below. + size_t buffer_size = enc_rsa_key_length + sizeof(WrappedRSAKey); + + if (wrapped_rsa_key == NULL || *wrapped_rsa_key_length < buffer_size) { + if (LogCategoryEnabled(kLoggingDumpDerivedKeys)) { + LOGW("[OEMCrypto_RewrapDeviceRSAKey30(): Wrapped Keybox Short Buffer]"); + } + *wrapped_rsa_key_length = buffer_size; + return OEMCrypto_ERROR_SHORT_BUFFER; + } + *wrapped_rsa_key_length = buffer_size; // Tell caller how much space we used. + if (NO_ERROR != crypto_engine->ValidateKeybox()) { + LOGE("[OEMCrypto_RewrapDeviceRSAKey30(): ERROR_KEYBOX_INVALID]"); + return OEMCrypto_ERROR_KEYBOX_INVALID; + } + SessionContext* session_ctx = crypto_engine->FindSession(session); + if (!session_ctx || !session_ctx->isValid()) { + LOGE("[OEMCrypto_RewrapDeviceRSAKey30(): ERROR_INVALID_SESSION]"); + return OEMCrypto_ERROR_INVALID_SESSION; + } + if (encrypted_message_key == NULL || encrypted_message_key_length == 0 + || enc_rsa_key == NULL || enc_rsa_key_iv == NULL) { + LOGE("[OEMCrypto_RewrapDeviceRSAKey30(): OEMCrypto_ERROR_INVALID_CONTEXT]"); + return OEMCrypto_ERROR_INVALID_CONTEXT; + } + + // Validate nonce + if (!session_ctx->CheckNonce(*nonce)) { + return OEMCrypto_ERROR_INVALID_NONCE; + } + session_ctx->FlushNonces(); + + if(!session_ctx->InstallRSAEncryptedKey(encrypted_message_key, + encrypted_message_key_length)) { + LOGE("OEMCrypto_RewrapDeviceRSAKey30: Error loading encrypted_message_key."); + return OEMCrypto_ERROR_UNKNOWN_FAILURE; + } + + // Decrypt RSA key. + std::vector pkcs8_rsa_key(enc_rsa_key_length); + if (!session_ctx->DecryptRSAKey(enc_rsa_key, enc_rsa_key_length, + enc_rsa_key_iv, &pkcs8_rsa_key[0])) { + return OEMCrypto_ERROR_INVALID_RSA_KEY; + } + size_t padding = pkcs8_rsa_key[enc_rsa_key_length - 1]; + if (padding > 16) { + LOGE("[OEMCrypto_RewrapDeviceRSAKey30(): Encrypted RSA has bad padding: %d]", + padding); + return OEMCrypto_ERROR_INVALID_RSA_KEY; + } + size_t rsa_key_length = enc_rsa_key_length - padding; + if (!session_ctx->LoadRSAKey(&pkcs8_rsa_key[0], rsa_key_length)) { + LOGE("[OEMCrypto_RewrapDeviceRSAKey30(): Failed to LoadRSAKey."); + return OEMCrypto_ERROR_INVALID_RSA_KEY; + } + + // Now we generate a wrapped keybox. + WrappedRSAKey* wrapped = reinterpret_cast(wrapped_rsa_key); + // Pick a random context and IV for generating keys. + if (!RAND_bytes(wrapped->context, sizeof(wrapped->context))) { + LOGE("[_RewrapDeviceRSAKey30(): RAND_bytes failed."); + return OEMCrypto_ERROR_UNKNOWN_FAILURE; + } + if (!RAND_bytes(wrapped->iv, sizeof(wrapped->iv))) { + LOGE("[_RewrapDeviceRSAKey30(): RAND_bytes failed."); + return OEMCrypto_ERROR_UNKNOWN_FAILURE; + } + // TODO(fredgc): Don't use the keybox to encrypt the wrapped RSA key. + const std::vector + context(wrapped->context, wrapped->context + sizeof(wrapped->context)); + // Generate mac and encryption keys for encrypting the signature. + if (!session_ctx->DeriveKeys(crypto_engine->keybox().device_key(), context, + context)) { + LOGE("[_RewrapDeviceRSAKey30(): DeriveKeys failed."); + return OEMCrypto_ERROR_UNKNOWN_FAILURE; + } + + // Encrypt rsa key with keybox. + if (!session_ctx->EncryptRSAKey(&pkcs8_rsa_key[0], enc_rsa_key_length, + wrapped->iv, wrapped->enc_rsa_key)) { + LOGE("[_RewrapDeviceRSAKey30(): EncrypteRSAKey failed."); + return OEMCrypto_ERROR_UNKNOWN_FAILURE; + } + // The wrapped keybox must be signed with the same key we verify with. I'll + // pick the server key, so I don't have to modify LoadRSAKey. + unsigned int sig_length = sizeof(wrapped->signature); + if (!HMAC(EVP_sha256(), &session_ctx->mac_key_server()[0], + session_ctx->mac_key_server().size(), wrapped->context, + buffer_size - sizeof(wrapped->signature), wrapped->signature, + &sig_length)) { + return OEMCrypto_ERROR_UNKNOWN_FAILURE; + } + if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) { + if (wvcdm::g_cutoff >= wvcdm::LOG_VERBOSE) { + dump_hex("wrapped_rsa_key", wrapped_rsa_key, *wrapped_rsa_key_length); + dump_hex("context", wrapped->context, sizeof(wrapped->context)); + dump_hex("iv", wrapped->iv, sizeof(wrapped->iv)); + } + } + return OEMCrypto_SUCCESS; +} + extern "C" OEMCryptoResult OEMCrypto_RewrapDeviceRSAKey(OEMCrypto_SESSION session, const uint8_t* message, @@ -844,7 +1012,7 @@ OEMCryptoResult OEMCrypto_RewrapDeviceRSAKey(OEMCrypto_SESSION session, uint8_t* wrapped_rsa_key, size_t* wrapped_rsa_key_length) { if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls | kLoggingTraceNonce)) { - LOGI("-- OEMCryptoResult OEMCrypto_RewrapDeviceRSAKey()\n"); + LOGI("-- OEMCryptoResult OEMCrypto_RewrapDeviceRSAKey(%d)\n", session); if (wvcdm::g_cutoff >= wvcdm::LOG_VERBOSE) { dump_hex("message", message, message_length); dump_hex("signature", signature, signature_length); @@ -914,70 +1082,58 @@ OEMCryptoResult OEMCrypto_RewrapDeviceRSAKey(OEMCrypto_SESSION session, session_ctx->FlushNonces(); // Decrypt RSA key. - uint8_t* pkcs8_rsa_key = new uint8_t[enc_rsa_key_length]; - OEMCryptoResult result = OEMCrypto_SUCCESS; + std::vector pkcs8_rsa_key(enc_rsa_key_length); if (!session_ctx->DecryptRSAKey(enc_rsa_key, enc_rsa_key_length, - enc_rsa_key_iv, pkcs8_rsa_key)) { - result = OEMCrypto_ERROR_INVALID_RSA_KEY; + enc_rsa_key_iv, &pkcs8_rsa_key[0])) { + return OEMCrypto_ERROR_INVALID_RSA_KEY; } size_t padding = pkcs8_rsa_key[enc_rsa_key_length - 1]; - if (result == OEMCrypto_SUCCESS) { - if (padding > 16) { - LOGE("[RewrapRSAKey(): Encrypted RSA has bad padding: %d]", padding); - result = OEMCrypto_ERROR_INVALID_RSA_KEY; - } + if (padding > 16) { + LOGE("[RewrapDeviceRSAKey(): Encrypted RSA has bad padding: %d]", + padding); + return OEMCrypto_ERROR_INVALID_RSA_KEY; } size_t rsa_key_length = enc_rsa_key_length - padding; // verify signature, verify RSA key, and load it. - if (result == OEMCrypto_SUCCESS) { - if (!session_ctx->LoadRSAKey(pkcs8_rsa_key, rsa_key_length, - message, message_length, - signature, signature_length)) { - result = OEMCrypto_ERROR_SIGNATURE_FAILURE; - // return OEMCrypto_ERROR_INVALID_RSA_KEY; - } + if (!session_ctx->ValidateMessage(message, message_length, signature, + signature_length)) { + LOGE("[RewrapDeviceRSAKey(): Could not verify signature]"); + return OEMCrypto_ERROR_SIGNATURE_FAILURE; + } + if (!session_ctx->LoadRSAKey(&pkcs8_rsa_key[0], rsa_key_length)) { + return OEMCrypto_ERROR_INVALID_RSA_KEY; } // Now we generate a wrapped keybox. WrappedRSAKey* wrapped = reinterpret_cast(wrapped_rsa_key); // Pick a random context and IV for generating keys. - if (result == OEMCrypto_SUCCESS) { - if (!RAND_bytes(wrapped->context, sizeof(wrapped->context))) { - result = OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - if (!RAND_bytes(wrapped->iv, sizeof(wrapped->iv))) { - result = OEMCrypto_ERROR_UNKNOWN_FAILURE; - } + if (!RAND_bytes(wrapped->context, sizeof(wrapped->context))) { + return OEMCrypto_ERROR_UNKNOWN_FAILURE; + } + if (!RAND_bytes(wrapped->iv, sizeof(wrapped->iv))) { + return OEMCrypto_ERROR_UNKNOWN_FAILURE; } const std::vector context(wrapped->context, wrapped->context + sizeof(wrapped->context)); // Generate mac and encryption keys for encrypting the signature. - if (result == OEMCrypto_SUCCESS) { - if (!session_ctx->DeriveKeys(crypto_engine->keybox().device_key(), context, - context)) { - result = OEMCrypto_ERROR_UNKNOWN_FAILURE; - } + if (!session_ctx->DeriveKeys(crypto_engine->keybox().device_key(), context, + context)) { + return OEMCrypto_ERROR_UNKNOWN_FAILURE; } // Encrypt rsa key with keybox. - if (result == OEMCrypto_SUCCESS) { - if (!session_ctx->EncryptRSAKey(pkcs8_rsa_key, enc_rsa_key_length, - wrapped->iv, wrapped->enc_rsa_key)) { - result = OEMCrypto_ERROR_UNKNOWN_FAILURE; - } + if (!session_ctx->EncryptRSAKey(&pkcs8_rsa_key[0], enc_rsa_key_length, + wrapped->iv, wrapped->enc_rsa_key)) { + return OEMCrypto_ERROR_UNKNOWN_FAILURE; } - delete[] pkcs8_rsa_key; - // The wrapped keybox must be signed with the same key we verify with. I'll // pick the server key, so I don't have to modify LoadRSAKey. - if (result == OEMCrypto_SUCCESS) { - unsigned int sig_length = sizeof(wrapped->signature); - if (!HMAC(EVP_sha256(), &session_ctx->mac_key_server()[0], - session_ctx->mac_key_server().size(), wrapped->context, - buffer_size - sizeof(wrapped->signature), wrapped->signature, - &sig_length)) { - result = OEMCrypto_ERROR_UNKNOWN_FAILURE; - } + unsigned int sig_length = sizeof(wrapped->signature); + if (!HMAC(EVP_sha256(), &session_ctx->mac_key_server()[0], + session_ctx->mac_key_server().size(), wrapped->context, + buffer_size - sizeof(wrapped->signature), wrapped->signature, + &sig_length)) { + return OEMCrypto_ERROR_UNKNOWN_FAILURE; } if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) { if (wvcdm::g_cutoff >= wvcdm::LOG_VERBOSE) { @@ -987,7 +1143,7 @@ OEMCryptoResult OEMCrypto_RewrapDeviceRSAKey(OEMCrypto_SESSION session, dump_hex("iv", wrapped->iv, sizeof(wrapped->iv)); } } - return result; + return OEMCrypto_SUCCESS; } extern "C" @@ -1002,12 +1158,13 @@ OEMCryptoResult OEMCrypto_LoadDeviceRSAKey(OEMCrypto_SESSION session, LOGE("OEMCrypto_LoadDeviceRSAKey: OEMCrypto Not Initialized."); return OEMCrypto_ERROR_UNKNOWN_FAILURE; } - if (!crypto_engine->supports_keybox()) { - // If we are not using keyboxes, the "wrapped RSA key" should actually be + if (crypto_engine->provisioning_method() == OEMCrypto_DrmCertificate) { + // If we are using a baked in cert, the "wrapped RSA key" should actually be // the magic value for baked-in certificates. if (wrapped_rsa_key_length != sizeof(kBakedInCertificateMagicBytes) || memcmp(kBakedInCertificateMagicBytes, wrapped_rsa_key, wrapped_rsa_key_length) != 0) { + LOGE("OEMCrypto_LoadDeviceRSAKey: Baked in Cert has wrong size."); return OEMCrypto_ERROR_INVALID_RSA_KEY; } else { return OEMCrypto_SUCCESS; @@ -1024,6 +1181,7 @@ OEMCryptoResult OEMCrypto_LoadDeviceRSAKey(OEMCrypto_SESSION session, dump_hex("iv", wrapped->iv, sizeof(wrapped->iv)); } } + // TODO(fredgc): Don't use the keybox to encrypt the wrapped RSA key. if (NO_ERROR != crypto_engine->ValidateKeybox()) { LOGE("[OEMCrypto_LoadDeviceRSAKey(): ERROR_KEYBOX_INVALID]"); return OEMCrypto_ERROR_KEYBOX_INVALID; @@ -1042,34 +1200,31 @@ OEMCryptoResult OEMCrypto_LoadDeviceRSAKey(OEMCrypto_SESSION session, return OEMCrypto_ERROR_UNKNOWN_FAILURE; } // Decrypt RSA key. - uint8_t* pkcs8_rsa_key = new uint8_t[wrapped_rsa_key_length - - sizeof(wrapped->signature)]; + std::vector pkcs8_rsa_key(wrapped_rsa_key_length + - sizeof(wrapped->signature)); size_t enc_rsa_key_length = wrapped_rsa_key_length - sizeof(WrappedRSAKey); - OEMCryptoResult result = OEMCrypto_SUCCESS; if (!session_ctx->DecryptRSAKey(wrapped->enc_rsa_key, enc_rsa_key_length, - wrapped->iv, pkcs8_rsa_key)) { - result = OEMCrypto_ERROR_INVALID_RSA_KEY; + wrapped->iv, &pkcs8_rsa_key[0])) { + return OEMCrypto_ERROR_INVALID_RSA_KEY; } size_t padding = pkcs8_rsa_key[enc_rsa_key_length - 1]; - if (result == OEMCrypto_SUCCESS) { - if (padding > 16) { - LOGE("[LoadDeviceRSAKey(): Encrypted RSA has bad padding: %d]", padding); - result = OEMCrypto_ERROR_INVALID_RSA_KEY; - } + if (padding > 16) { + LOGE("[LoadDeviceRSAKey(): Encrypted RSA has bad padding: %d]", padding); + return OEMCrypto_ERROR_INVALID_RSA_KEY; } size_t rsa_key_length = enc_rsa_key_length - padding; // verify signature. - if (result == OEMCrypto_SUCCESS) { - if (!session_ctx->LoadRSAKey( - pkcs8_rsa_key, rsa_key_length, wrapped->context, - wrapped_rsa_key_length - sizeof(wrapped->signature), - wrapped->signature, sizeof(wrapped->signature))) { - result = OEMCrypto_ERROR_SIGNATURE_FAILURE; - // return OEMCrypto_ERROR_INVALID_RSA_KEY; - } + if (!session_ctx->ValidateMessage( + wrapped->context, + wrapped_rsa_key_length - sizeof(wrapped->signature), + wrapped->signature, sizeof(wrapped->signature))) { + LOGE("[LoadDeviceRSAKey(): Could not verify signature]"); + return OEMCrypto_ERROR_SIGNATURE_FAILURE; } - delete[] pkcs8_rsa_key; - return result; + if (!session_ctx->LoadRSAKey(&pkcs8_rsa_key[0], rsa_key_length)) { + return OEMCrypto_ERROR_INVALID_RSA_KEY; + } + return OEMCrypto_SUCCESS; } extern "C" @@ -1208,8 +1363,7 @@ OEMCryptoResult OEMCrypto_DeriveKeysFromSessionKey( extern "C" uint32_t OEMCrypto_APIVersion() { - // TODO(fredgc): Implement new API. - return 11; + return 12; } extern "C" @@ -1319,7 +1473,7 @@ OEMCryptoResult OEMCrypto_Generic_Encrypt(OEMCrypto_SESSION session, return OEMCrypto_ERROR_UNKNOWN_FAILURE; } if (NO_ERROR != crypto_engine->ValidateKeybox()) { - LOGE("[OEMCrypto_Generic_Enrcypt(): ERROR_KEYBOX_INVALID]"); + LOGE("[OEMCrypto_Generic_Encrypt(): ERROR_KEYBOX_INVALID]"); return OEMCrypto_ERROR_KEYBOX_INVALID; } SessionContext* session_ctx = crypto_engine->FindSession(session);