1 /* 2 * SPDX-FileCopyrightText: Copyright (c) 2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved. 3 * SPDX-License-Identifier: MIT 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining a 6 * copy of this software and associated documentation files (the "Software"), 7 * to deal in the Software without restriction, including without limitation 8 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 * and/or sell copies of the Software, and to permit persons to whom the 10 * Software is furnished to do so, subject to the following conditions: 11 * 12 * The above copyright notice and this permission notice shall be included in 13 * all copies or substantial portions of the Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 * DEALINGS IN THE SOFTWARE. 22 */ 23 24 /*! 25 * Provides the implementation for all GH100 SPDM certificate HAL interfaces. 26 */ 27 28 /* ------------------------ Includes --------------------------------------- */ 29 #include "nvRmReg.h" 30 #include "gpu/spdm/spdm.h" 31 #include "gpu/spdm/libspdm_includes.h" 32 #include "spdm/rmspdmvendordef.h" 33 #include "flcnretval.h" 34 35 /* ------------------------ Macros ----------------------------------------- */ 36 #define DER_LONG_FORM_LENGTH_FIELD_BIT (0x80) 37 #define DER_CERT_SIZE_FIELD_LENGTH (0x4) 38 39 #define SPDM_MAX_ENCODED_CERT_CHAIN_SIZE (0x1400) 40 41 #define SPDM_PEM_BEGIN_CERTIFICATE "-----BEGIN CERTIFICATE-----\n" 42 #define SPDM_PEM_END_CERTIFICATE "-----END CERTIFICATE-----\n" 43 44 #define SPDM_L1_CERTIFICATE_PEM "-----BEGIN CERTIFICATE-----\n"\ 45 "MIICCzCCAZCgAwIBAgIQLTZwscoQBBHB/sDoKgZbVDAKBggqhkjOPQQDAzA1MSIw\n"\ 46 "IAYDVQQDDBlOVklESUEgRGV2aWNlIElkZW50aXR5IENBMQ8wDQYDVQQKDAZOVklE\n"\ 47 "SUEwIBcNMjExMTA1MDAwMDAwWhgPOTk5OTEyMzEyMzU5NTlaMDUxIjAgBgNVBAMM\n"\ 48 "GU5WSURJQSBEZXZpY2UgSWRlbnRpdHkgQ0ExDzANBgNVBAoMBk5WSURJQTB2MBAG\n"\ 49 "ByqGSM49AgEGBSuBBAAiA2IABA5MFKM7+KViZljbQSlgfky/RRnEQScW9NDZF8SX\n"\ 50 "gAW96r6u/Ve8ZggtcYpPi2BS4VFu6KfEIrhN6FcHG7WP05W+oM+hxj7nyA1r1jkB\n"\ 51 "2Ry70YfThX3Ba1zOryOP+MJ9vaNjMGEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8B\n"\ 52 "Af8EBAMCAQYwHQYDVR0OBBYEFFeF/4PyY8xlfWi3Olv0jUrL+0lfMB8GA1UdIwQY\n"\ 53 "MBaAFFeF/4PyY8xlfWi3Olv0jUrL+0lfMAoGCCqGSM49BAMDA2kAMGYCMQCPeFM3\n"\ 54 "TASsKQVaT+8S0sO9u97PVGCpE9d/I42IT7k3UUOLSR/qvJynVOD1vQKVXf0CMQC+\n"\ 55 "EY55WYoDBvs2wPAH1Gw4LbcwUN8QCff8bFmV4ZxjCRr4WXTLFHBKjbfneGSBWwA=\n"\ 56 "-----END CERTIFICATE-----\n" 57 58 #define SPDM_L2_CERTIFICATE_PEM "-----BEGIN CERTIFICATE-----\n"\ 59 "MIICijCCAhCgAwIBAgIQTCVe3jvQAb8/SjtgX8qJijAKBggqhkjOPQQDAzA1MSIw\n"\ 60 "IAYDVQQDDBlOVklESUEgRGV2aWNlIElkZW50aXR5IENBMQ8wDQYDVQQKDAZOVklE\n"\ 61 "SUEwIBcNMjIwMTEyMDAwMDAwWhgPOTk5OTEyMzEyMzU5NTlaMD0xHjAcBgNVBAMM\n"\ 62 "FU5WSURJQSBHSDEwMCBJZGVudGl0eTEbMBkGA1UECgwSTlZJRElBIENvcnBvcmF0\n"\ 63 "aW9uMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAE+pg+tDUuILlZILk5wg22YEJ9Oh6c\n"\ 64 "yPcsv3IvgRWcV4LeZK1pTCoQDIplZ0E4qsLG3G04pxsbMhxbqkiz9pqlTV2rtuVg\n"\ 65 "SmIqnSYkU1jWXsPS9oVLCGE8VRLl1JvqyOxUo4HaMIHXMA8GA1UdEwEB/wQFMAMB\n"\ 66 "Af8wDgYDVR0PAQH/BAQDAgEGMDsGA1UdHwQ0MDIwMKAuoCyGKmh0dHA6Ly9jcmwu\n"\ 67 "bmRpcy5udmlkaWEuY29tL2NybC9sMS1yb290LmNybDA3BggrBgEFBQcBAQQrMCkw\n"\ 68 "JwYIKwYBBQUHMAGGG2h0dHA6Ly9vY3NwLm5kaXMubnZpZGlhLmNvbTAdBgNVHQ4E\n"\ 69 "FgQUB0Kg6wOcgGB7oUFhmU2uJffCmx4wHwYDVR0jBBgwFoAUV4X/g/JjzGV9aLc6\n"\ 70 "W/SNSsv7SV8wCgYIKoZIzj0EAwMDaAAwZQIxAPIQhnveFxYIrPzBqViT2I34SfS4\n"\ 71 "JGWFnk/1UcdmgJmp+7l6rH/C4qxwntYSgeYrlQIwdjQuofHnhd1RL09OBO34566J\n"\ 72 "C9bYAosT/86cCojiGjhLnal9hJOH0nS/lrbaoc5a\n"\ 73 "-----END CERTIFICATE-----\n" 74 75 #define SPDM_L3_CERTIFICATE_PEM "-----BEGIN CERTIFICATE-----\n"\ 76 "MIICqjCCAi+gAwIBAgIQav5xhPkiMsjfeyQiYXduVjAKBggqhkjOPQQDAzA9MR4w\n"\ 77 "HAYDVQQDDBVOVklESUEgR0gxMDAgSWRlbnRpdHkxGzAZBgNVBAoMEk5WSURJQSBD\n"\ 78 "b3Jwb3JhdGlvbjAgFw0yMjAzMDEwMDAwMDBaGA85OTk5MTIzMTIzNTk1OVowUzEn\n"\ 79 "MCUGA1UEAwweTlZJRElBIEdIMTAwIFByb3Zpc2lvbmVyIElDQSAxMRswGQYDVQQK\n"\ 80 "DBJOVklESUEgQ29ycG9yYXRpb24xCzAJBgNVBAYTAlVTMHYwEAYHKoZIzj0CAQYF\n"\ 81 "K4EEACIDYgAEzUdWqjn1OlXhLfFOKAFTghqG+Q3zF4xgSBbZsUEyWYCC3rKjE9Nn\n"\ 82 "o88ZpBQx85Oo0PkqP2dwoMVNTQMv5cvy9jLaTvSTXZwN2HQHE9u7x7BIYrWi0sG3\n"\ 83 "5q1IJNSOGO5Lo4HbMIHYMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEG\n"\ 84 "MDwGA1UdHwQ1MDMwMaAvoC2GK2h0dHA6Ly9jcmwubmRpcy5udmlkaWEuY29tL2Ny\n"\ 85 "bC9sMi1naDEwMC5jcmwwNwYIKwYBBQUHAQEEKzApMCcGCCsGAQUFBzABhhtodHRw\n"\ 86 "Oi8vb2NzcC5uZGlzLm52aWRpYS5jb20wHQYDVR0OBBYEFCloyxYs0HeVcqJ5EAPm\n"\ 87 "nroMzAqUMB8GA1UdIwQYMBaAFAdCoOsDnIBge6FBYZlNriX3wpseMAoGCCqGSM49\n"\ 88 "BAMDA2kAMGYCMQDK0BCr49DNJ48Yh5wu388bZifDFxAsiUS4U1fGmpJZFhCbODH6\n"\ 89 "mRwcMxp6EOayZuYCMQDYKTyNc2FxWFuhHtdCE3ls4S7SInehdErTZNuhFymc4YOM\n"\ 90 "6VlLWTY/CM+resjjqxQ=\n"\ 91 "-----END CERTIFICATE-----\n" 92 93 const static NvU8 SPDM_L1_CERTIFICATE_DER[527] = 94 { 95 0x30, 0x82, 0x02, 0x0b, 0x30, 0x82, 0x01, 0x90, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0x2d, 96 0x36, 0x70, 0xb1, 0xca, 0x10, 0x04, 0x11, 0xc1, 0xfe, 0xc0, 0xe8, 0x2a, 0x06, 0x5b, 0x54, 0x30, 97 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x03, 0x30, 0x35, 0x31, 0x22, 0x30, 98 0x20, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x19, 0x4e, 0x56, 0x49, 0x44, 0x49, 0x41, 0x20, 0x44, 99 0x65, 0x76, 0x69, 0x63, 0x65, 0x20, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x20, 0x43, 100 0x41, 0x31, 0x0f, 0x30, 0x0d, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x06, 0x4e, 0x56, 0x49, 0x44, 101 0x49, 0x41, 0x30, 0x20, 0x17, 0x0d, 0x32, 0x31, 0x31, 0x31, 0x30, 0x35, 0x30, 0x30, 0x30, 0x30, 102 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x39, 0x39, 0x39, 0x39, 0x31, 0x32, 0x33, 0x31, 0x32, 0x33, 0x35, 103 0x39, 0x35, 0x39, 0x5a, 0x30, 0x35, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 104 0x19, 0x4e, 0x56, 0x49, 0x44, 0x49, 0x41, 0x20, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x20, 0x49, 105 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x20, 0x43, 0x41, 0x31, 0x0f, 0x30, 0x0d, 0x06, 0x03, 106 0x55, 0x04, 0x0a, 0x0c, 0x06, 0x4e, 0x56, 0x49, 0x44, 0x49, 0x41, 0x30, 0x76, 0x30, 0x10, 0x06, 107 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x22, 0x03, 108 0x62, 0x00, 0x04, 0x0e, 0x4c, 0x14, 0xa3, 0x3b, 0xf8, 0xa5, 0x62, 0x66, 0x58, 0xdb, 0x41, 0x29, 109 0x60, 0x7e, 0x4c, 0xbf, 0x45, 0x19, 0xc4, 0x41, 0x27, 0x16, 0xf4, 0xd0, 0xd9, 0x17, 0xc4, 0x97, 110 0x80, 0x05, 0xbd, 0xea, 0xbe, 0xae, 0xfd, 0x57, 0xbc, 0x66, 0x08, 0x2d, 0x71, 0x8a, 0x4f, 0x8b, 111 0x60, 0x52, 0xe1, 0x51, 0x6e, 0xe8, 0xa7, 0xc4, 0x22, 0xb8, 0x4d, 0xe8, 0x57, 0x07, 0x1b, 0xb5, 112 0x8f, 0xd3, 0x95, 0xbe, 0xa0, 0xcf, 0xa1, 0xc6, 0x3e, 0xe7, 0xc8, 0x0d, 0x6b, 0xd6, 0x39, 0x01, 113 0xd9, 0x1c, 0xbb, 0xd1, 0x87, 0xd3, 0x85, 0x7d, 0xc1, 0x6b, 0x5c, 0xce, 0xaf, 0x23, 0x8f, 0xf8, 114 0xc2, 0x7d, 0xbd, 0xa3, 0x63, 0x30, 0x61, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 115 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 116 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 117 0x16, 0x04, 0x14, 0x57, 0x85, 0xff, 0x83, 0xf2, 0x63, 0xcc, 0x65, 0x7d, 0x68, 0xb7, 0x3a, 0x5b, 118 0xf4, 0x8d, 0x4a, 0xcb, 0xfb, 0x49, 0x5f, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 119 0x30, 0x16, 0x80, 0x14, 0x57, 0x85, 0xff, 0x83, 0xf2, 0x63, 0xcc, 0x65, 0x7d, 0x68, 0xb7, 0x3a, 120 0x5b, 0xf4, 0x8d, 0x4a, 0xcb, 0xfb, 0x49, 0x5f, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 121 0x3d, 0x04, 0x03, 0x03, 0x03, 0x69, 0x00, 0x30, 0x66, 0x02, 0x31, 0x00, 0x8f, 0x78, 0x53, 0x37, 122 0x4c, 0x04, 0xac, 0x29, 0x05, 0x5a, 0x4f, 0xef, 0x12, 0xd2, 0xc3, 0xbd, 0xbb, 0xde, 0xcf, 0x54, 123 0x60, 0xa9, 0x13, 0xd7, 0x7f, 0x23, 0x8d, 0x88, 0x4f, 0xb9, 0x37, 0x51, 0x43, 0x8b, 0x49, 0x1f, 124 0xea, 0xbc, 0x9c, 0xa7, 0x54, 0xe0, 0xf5, 0xbd, 0x02, 0x95, 0x5d, 0xfd, 0x02, 0x31, 0x00, 0xbe, 125 0x11, 0x8e, 0x79, 0x59, 0x8a, 0x03, 0x06, 0xfb, 0x36, 0xc0, 0xf0, 0x07, 0xd4, 0x6c, 0x38, 0x2d, 126 0xb7, 0x30, 0x50, 0xdf, 0x10, 0x09, 0xf7, 0xfc, 0x6c, 0x59, 0x95, 0xe1, 0x9c, 0x63, 0x09, 0x1a, 127 0xf8, 0x59, 0x74, 0xcb, 0x14, 0x70, 0x4a, 0x8d, 0xb7, 0xe7, 0x78, 0x64, 0x81, 0x5b, 0x00 128 }; 129 130 const static NvU8 SPDM_L2_CERTIFICATE_DER[654] = 131 { 132 0x30, 0x82, 0x02, 0x8a, 0x30, 0x82, 0x02, 0x10, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0x4c, 133 0x25, 0x5e, 0xde, 0x3b, 0xd0, 0x01, 0xbf, 0x3f, 0x4a, 0x3b, 0x60, 0x5f, 0xca, 0x89, 0x8a, 0x30, 134 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x03, 0x30, 0x35, 0x31, 0x22, 0x30, 135 0x20, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x19, 0x4e, 0x56, 0x49, 0x44, 0x49, 0x41, 0x20, 0x44, 136 0x65, 0x76, 0x69, 0x63, 0x65, 0x20, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x20, 0x43, 137 0x41, 0x31, 0x0f, 0x30, 0x0d, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x06, 0x4e, 0x56, 0x49, 0x44, 138 0x49, 0x41, 0x30, 0x20, 0x17, 0x0d, 0x32, 0x32, 0x30, 0x31, 0x31, 0x32, 0x30, 0x30, 0x30, 0x30, 139 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x39, 0x39, 0x39, 0x39, 0x31, 0x32, 0x33, 0x31, 0x32, 0x33, 0x35, 140 0x39, 0x35, 0x39, 0x5a, 0x30, 0x3d, 0x31, 0x1e, 0x30, 0x1c, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 141 0x15, 0x4e, 0x56, 0x49, 0x44, 0x49, 0x41, 0x20, 0x47, 0x48, 0x31, 0x30, 0x30, 0x20, 0x49, 0x64, 142 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x31, 0x1b, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 143 0x12, 0x4e, 0x56, 0x49, 0x44, 0x49, 0x41, 0x20, 0x43, 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61, 0x74, 144 0x69, 0x6f, 0x6e, 0x30, 0x76, 0x30, 0x10, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 145 0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x22, 0x03, 0x62, 0x00, 0x04, 0xfa, 0x98, 0x3e, 0xb4, 0x35, 146 0x2e, 0x20, 0xb9, 0x59, 0x20, 0xb9, 0x39, 0xc2, 0x0d, 0xb6, 0x60, 0x42, 0x7d, 0x3a, 0x1e, 0x9c, 147 0xc8, 0xf7, 0x2c, 0xbf, 0x72, 0x2f, 0x81, 0x15, 0x9c, 0x57, 0x82, 0xde, 0x64, 0xad, 0x69, 0x4c, 148 0x2a, 0x10, 0x0c, 0x8a, 0x65, 0x67, 0x41, 0x38, 0xaa, 0xc2, 0xc6, 0xdc, 0x6d, 0x38, 0xa7, 0x1b, 149 0x1b, 0x32, 0x1c, 0x5b, 0xaa, 0x48, 0xb3, 0xf6, 0x9a, 0xa5, 0x4d, 0x5d, 0xab, 0xb6, 0xe5, 0x60, 150 0x4a, 0x62, 0x2a, 0x9d, 0x26, 0x24, 0x53, 0x58, 0xd6, 0x5e, 0xc3, 0xd2, 0xf6, 0x85, 0x4b, 0x08, 151 0x61, 0x3c, 0x55, 0x12, 0xe5, 0xd4, 0x9b, 0xea, 0xc8, 0xec, 0x54, 0xa3, 0x81, 0xda, 0x30, 0x81, 152 0xd7, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 153 0x01, 0xff, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 154 0x01, 0x06, 0x30, 0x3b, 0x06, 0x03, 0x55, 0x1d, 0x1f, 0x04, 0x34, 0x30, 0x32, 0x30, 0x30, 0xa0, 155 0x2e, 0xa0, 0x2c, 0x86, 0x2a, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x72, 0x6c, 0x2e, 156 0x6e, 0x64, 0x69, 0x73, 0x2e, 0x6e, 0x76, 0x69, 0x64, 0x69, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 157 0x63, 0x72, 0x6c, 0x2f, 0x6c, 0x31, 0x2d, 0x72, 0x6f, 0x6f, 0x74, 0x2e, 0x63, 0x72, 0x6c, 0x30, 158 0x37, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x01, 0x01, 0x04, 0x2b, 0x30, 0x29, 0x30, 159 0x27, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x86, 0x1b, 0x68, 0x74, 0x74, 160 0x70, 0x3a, 0x2f, 0x2f, 0x6f, 0x63, 0x73, 0x70, 0x2e, 0x6e, 0x64, 0x69, 0x73, 0x2e, 0x6e, 0x76, 161 0x69, 0x64, 0x69, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 162 0x16, 0x04, 0x14, 0x07, 0x42, 0xa0, 0xeb, 0x03, 0x9c, 0x80, 0x60, 0x7b, 0xa1, 0x41, 0x61, 0x99, 163 0x4d, 0xae, 0x25, 0xf7, 0xc2, 0x9b, 0x1e, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 164 0x30, 0x16, 0x80, 0x14, 0x57, 0x85, 0xff, 0x83, 0xf2, 0x63, 0xcc, 0x65, 0x7d, 0x68, 0xb7, 0x3a, 165 0x5b, 0xf4, 0x8d, 0x4a, 0xcb, 0xfb, 0x49, 0x5f, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 166 0x3d, 0x04, 0x03, 0x03, 0x03, 0x68, 0x00, 0x30, 0x65, 0x02, 0x31, 0x00, 0xf2, 0x10, 0x86, 0x7b, 167 0xde, 0x17, 0x16, 0x08, 0xac, 0xfc, 0xc1, 0xa9, 0x58, 0x93, 0xd8, 0x8d, 0xf8, 0x49, 0xf4, 0xb8, 168 0x24, 0x65, 0x85, 0x9e, 0x4f, 0xf5, 0x51, 0xc7, 0x66, 0x80, 0x99, 0xa9, 0xfb, 0xb9, 0x7a, 0xac, 169 0x7f, 0xc2, 0xe2, 0xac, 0x70, 0x9e, 0xd6, 0x12, 0x81, 0xe6, 0x2b, 0x95, 0x02, 0x30, 0x76, 0x34, 170 0x2e, 0xa1, 0xf1, 0xe7, 0x85, 0xdd, 0x51, 0x2f, 0x4f, 0x4e, 0x04, 0xed, 0xf8, 0xe7, 0xae, 0x89, 171 0x0b, 0xd6, 0xd8, 0x02, 0x8b, 0x13, 0xff, 0xce, 0x9c, 0x0a, 0x88, 0xe2, 0x1a, 0x38, 0x4b, 0x9d, 172 0xa9, 0x7d, 0x84, 0x93, 0x87, 0xd2, 0x74, 0xbf, 0x96, 0xb6, 0xda, 0xa1, 0xce, 0x5a, 173 }; 174 175 const static NvU8 SPDM_L3_CERTIFICATE_DER[686] = 176 { 177 0x30, 0x82, 0x02, 0xaa, 0x30, 0x82, 0x02, 0x2f, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0x6a, 178 0xfe, 0x71, 0x84, 0xf9, 0x22, 0x32, 0xc8, 0xdf, 0x7b, 0x24, 0x22, 0x61, 0x77, 0x6e, 0x56, 0x30, 179 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x03, 0x30, 0x3d, 0x31, 0x1e, 0x30, 180 0x1c, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x15, 0x4e, 0x56, 0x49, 0x44, 0x49, 0x41, 0x20, 0x47, 181 0x48, 0x31, 0x30, 0x30, 0x20, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x31, 0x1b, 0x30, 182 0x19, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x12, 0x4e, 0x56, 0x49, 0x44, 0x49, 0x41, 0x20, 0x43, 183 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x30, 0x20, 0x17, 0x0d, 0x32, 0x32, 184 0x30, 0x33, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x39, 0x39, 0x39, 185 0x39, 0x31, 0x32, 0x33, 0x31, 0x32, 0x33, 0x35, 0x39, 0x35, 0x39, 0x5a, 0x30, 0x53, 0x31, 0x27, 186 0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x1e, 0x4e, 0x56, 0x49, 0x44, 0x49, 0x41, 0x20, 187 0x47, 0x48, 0x31, 0x30, 0x30, 0x20, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 188 0x72, 0x20, 0x49, 0x43, 0x41, 0x20, 0x31, 0x31, 0x1b, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, 0x0a, 189 0x0c, 0x12, 0x4e, 0x56, 0x49, 0x44, 0x49, 0x41, 0x20, 0x43, 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61, 190 0x74, 0x69, 0x6f, 0x6e, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 191 0x53, 0x30, 0x76, 0x30, 0x10, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x05, 192 0x2b, 0x81, 0x04, 0x00, 0x22, 0x03, 0x62, 0x00, 0x04, 0xcd, 0x47, 0x56, 0xaa, 0x39, 0xf5, 0x3a, 193 0x55, 0xe1, 0x2d, 0xf1, 0x4e, 0x28, 0x01, 0x53, 0x82, 0x1a, 0x86, 0xf9, 0x0d, 0xf3, 0x17, 0x8c, 194 0x60, 0x48, 0x16, 0xd9, 0xb1, 0x41, 0x32, 0x59, 0x80, 0x82, 0xde, 0xb2, 0xa3, 0x13, 0xd3, 0x67, 195 0xa3, 0xcf, 0x19, 0xa4, 0x14, 0x31, 0xf3, 0x93, 0xa8, 0xd0, 0xf9, 0x2a, 0x3f, 0x67, 0x70, 0xa0, 196 0xc5, 0x4d, 0x4d, 0x03, 0x2f, 0xe5, 0xcb, 0xf2, 0xf6, 0x32, 0xda, 0x4e, 0xf4, 0x93, 0x5d, 0x9c, 197 0x0d, 0xd8, 0x74, 0x07, 0x13, 0xdb, 0xbb, 0xc7, 0xb0, 0x48, 0x62, 0xb5, 0xa2, 0xd2, 0xc1, 0xb7, 198 0xe6, 0xad, 0x48, 0x24, 0xd4, 0x8e, 0x18, 0xee, 0x4b, 0xa3, 0x81, 0xdb, 0x30, 0x81, 0xd8, 0x30, 199 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 200 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 201 0x30, 0x3c, 0x06, 0x03, 0x55, 0x1d, 0x1f, 0x04, 0x35, 0x30, 0x33, 0x30, 0x31, 0xa0, 0x2f, 0xa0, 202 0x2d, 0x86, 0x2b, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x72, 0x6c, 0x2e, 0x6e, 0x64, 203 0x69, 0x73, 0x2e, 0x6e, 0x76, 0x69, 0x64, 0x69, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x72, 204 0x6c, 0x2f, 0x6c, 0x32, 0x2d, 0x67, 0x68, 0x31, 0x30, 0x30, 0x2e, 0x63, 0x72, 0x6c, 0x30, 0x37, 205 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x01, 0x01, 0x04, 0x2b, 0x30, 0x29, 0x30, 0x27, 206 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x86, 0x1b, 0x68, 0x74, 0x74, 0x70, 207 0x3a, 0x2f, 0x2f, 0x6f, 0x63, 0x73, 0x70, 0x2e, 0x6e, 0x64, 0x69, 0x73, 0x2e, 0x6e, 0x76, 0x69, 208 0x64, 0x69, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 209 0x04, 0x14, 0x29, 0x68, 0xcb, 0x16, 0x2c, 0xd0, 0x77, 0x95, 0x72, 0xa2, 0x79, 0x10, 0x03, 0xe6, 210 0x9e, 0xba, 0x0c, 0xcc, 0x0a, 0x94, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 211 0x16, 0x80, 0x14, 0x07, 0x42, 0xa0, 0xeb, 0x03, 0x9c, 0x80, 0x60, 0x7b, 0xa1, 0x41, 0x61, 0x99, 212 0x4d, 0xae, 0x25, 0xf7, 0xc2, 0x9b, 0x1e, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 213 0x04, 0x03, 0x03, 0x03, 0x69, 0x00, 0x30, 0x66, 0x02, 0x31, 0x00, 0xca, 0xd0, 0x10, 0xab, 0xe3, 214 0xd0, 0xcd, 0x27, 0x8f, 0x18, 0x87, 0x9c, 0x2e, 0xdf, 0xcf, 0x1b, 0x66, 0x27, 0xc3, 0x17, 0x10, 215 0x2c, 0x89, 0x44, 0xb8, 0x53, 0x57, 0xc6, 0x9a, 0x92, 0x59, 0x16, 0x10, 0x9b, 0x38, 0x31, 0xfa, 216 0x99, 0x1c, 0x1c, 0x33, 0x1a, 0x7a, 0x10, 0xe6, 0xb2, 0x66, 0xe6, 0x02, 0x31, 0x00, 0xd8, 0x29, 217 0x3c, 0x8d, 0x73, 0x61, 0x71, 0x58, 0x5b, 0xa1, 0x1e, 0xd7, 0x42, 0x13, 0x79, 0x6c, 0xe1, 0x2e, 218 0xd2, 0x22, 0x77, 0xa1, 0x74, 0x4a, 0xd3, 0x64, 0xdb, 0xa1, 0x17, 0x29, 0x9c, 0xe1, 0x83, 0x8c, 219 0xe9, 0x59, 0x4b, 0x59, 0x36, 0x3f, 0x08, 0xcf, 0xab, 0x7a, 0xc8, 0xe3, 0xab, 0x14, 220 }; 221 222 /* ------------------------ Static Functions ------------------------------- */ 223 /*! 224 @param pCert : The pointer to certification chain start 225 @param bufferEnd : The pointer to certification chain end 226 @parsm pCertLength : The pointer to store return certification size 227 228 @return Return NV-OK if no error. 229 230 * Static function that calculates the length of the X509 certificate in DER/TLV 231 * format. It assumes that the certificate is valid. 232 */ 233 static NV_STATUS 234 _calcX509CertSize 235 ( 236 NvU8 *pCert, 237 NvU8 *bufferEnd, 238 NvU32 *pCertLength 239 ) 240 { 241 // The cert is in TLV format. 242 NvU32 certSize = pCert[1]; 243 244 // Check to make sure that some data exists after SPDM header, and it is enough to check cert size. 245 if (pCert + DER_CERT_SIZE_FIELD_LENGTH >= bufferEnd || 246 pCert + DER_CERT_SIZE_FIELD_LENGTH <= pCert) 247 { 248 NV_PRINTF(LEVEL_ERROR, " %s: pCert + DER_CERT_SIZE_FIELD_LENGTH(0x%x) is not valid value !! \n", 249 __FUNCTION__, DER_CERT_SIZE_FIELD_LENGTH); 250 251 return NV_ERR_BUFFER_TOO_SMALL; 252 } 253 254 // Check if the length is in DER longform. 255 // MSB in the length field is set for long form notation. 256 // fields. 257 if (certSize & DER_LONG_FORM_LENGTH_FIELD_BIT) 258 { 259 // 260 // The remaining bits in the length field indicate the 261 // number of following bytes used to represent the length. 262 // in base 256, most significant digit first. 263 // 264 NvU32 numLenBytes = certSize & 0x3f; 265 NvU8 *pStart = &pCert[2]; 266 NvU8 *pEnd = pStart + numLenBytes; // NOTE: Don't need to subtract numLenBytes 1 here. 267 268 // Checking for buffer overflow. 269 if (pEnd > bufferEnd) 270 { 271 return NV_ERR_BUFFER_TOO_SMALL; 272 } 273 274 certSize = *pStart; 275 while (++pStart < pEnd) 276 { 277 certSize = (certSize << 8) + *pStart ; 278 } 279 // Total cert length includes the Tag + length 280 // Adding it here. 281 certSize += 2 + numLenBytes; 282 } 283 284 // 285 // Check to make sure we have not hit end of buffer, and there is space for AK cert. 286 // Check for underflow as well. This makes sure we haven't missed the calculation to 287 // go past the end of the buffer 288 // 289 if (pCert + (certSize - 1) > bufferEnd || 290 pCert + (certSize - 1) <= pCert) 291 { 292 NV_PRINTF(LEVEL_ERROR, " %s: pCert + (certSize(0x%x) - 1) is not a valid value !! \n", 293 __FUNCTION__, certSize); 294 295 return NV_ERR_BUFFER_TOO_SMALL; 296 } 297 298 *pCertLength = certSize; 299 return NV_OK; 300 } 301 302 static NV_STATUS 303 pem_write_buffer 304 ( 305 NvU8 const *der, 306 NvU64 derLen, 307 NvU8 *buffer, 308 NvU64 bufferLen, 309 NvU64 *bufferUsed 310 ) 311 { 312 static const NvU8 base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 313 NvU64 i, tmp, size; 314 NvU64 printed = 0; 315 NvU8 *ptr = buffer; 316 317 // Base64 encoded size 318 size = (derLen + 2) / 3 * 4; 319 320 // Add 1 byte per 64 for newline 321 size = size + (size + 63) / 64; 322 323 // Add header excluding the terminating null and footer including the null 324 size += sizeof(SPDM_PEM_BEGIN_CERTIFICATE) - 1 + 325 sizeof(SPDM_PEM_END_CERTIFICATE); 326 327 if (bufferLen < size) 328 { 329 return NV_ERR_BUFFER_TOO_SMALL; 330 } 331 332 portMemCopy(ptr, bufferLen - (ptr - buffer), SPDM_PEM_BEGIN_CERTIFICATE, 333 sizeof(SPDM_PEM_BEGIN_CERTIFICATE) - 1); 334 ptr += sizeof(SPDM_PEM_BEGIN_CERTIFICATE) - 1; 335 336 for (i = 0; (i + 2) < derLen; i += 3) 337 { 338 tmp = (der[i] << 16) | (der[i + 1] << 8) | (der[i + 2]); 339 *ptr++ = base64[(tmp >> 18) & 63]; 340 *ptr++ = base64[(tmp >> 12) & 63]; 341 *ptr++ = base64[(tmp >> 6) & 63]; 342 *ptr++ = base64[(tmp >> 0) & 63]; 343 344 printed += 4; 345 if (printed == 64) 346 { 347 *ptr++ = '\n'; 348 printed = 0; 349 } 350 } 351 352 if ((i == derLen) && (printed != 0)) 353 { 354 *ptr++ = '\n'; 355 } 356 357 // 1 byte extra 358 if (i == (derLen - 1)) 359 { 360 tmp = der[i] << 4; 361 *ptr++ = base64[(tmp >> 6) & 63]; 362 *ptr++ = base64[(tmp >> 0) & 63]; 363 *ptr++ = '='; 364 *ptr++ = '='; 365 *ptr++ = '\n'; 366 } 367 368 // 2 byte extra 369 if (i == (derLen - 2)) 370 { 371 tmp = ((der[i] << 8) | (der[i + 1])) << 2; 372 *ptr++ = base64[(tmp >> 12) & 63]; 373 *ptr++ = base64[(tmp >> 6) & 63]; 374 *ptr++ = base64[(tmp >> 0) & 63]; 375 *ptr++ = '='; 376 *ptr++ = '\n'; 377 } 378 379 portMemCopy(ptr, bufferLen - (ptr - buffer), SPDM_PEM_END_CERTIFICATE, 380 sizeof(SPDM_PEM_END_CERTIFICATE)); 381 ptr += sizeof(SPDM_PEM_END_CERTIFICATE); 382 383 *bufferUsed = size; 384 return NV_OK; 385 } 386 387 /*! 388 * Static function builds the cert chain in DER format. It is assumed that 389 * the all the certificates are valid. Also it is assumed that there is a valid 390 * spdm session already established. 391 */ 392 static NV_STATUS 393 _spdmBuildCertChainDer 394 ( 395 NvU8 *pFirstCert, 396 NvU32 firstCertSize, 397 NvU8 *pSecondCert, 398 NvU32 secondCertSize, 399 NvU8 *pOutBuffer, 400 size_t *outBufferSize 401 ) 402 { 403 NvU64 remainingOutBufferSize = 0; 404 NvU64 totalSize = 0; 405 void *pPortMemCopyStatus = NULL; 406 407 if (pFirstCert == NULL || pSecondCert == NULL || pOutBuffer == NULL || outBufferSize == NULL) 408 { 409 return NV_ERR_INVALID_ARGUMENT; 410 } 411 412 // Calculate the total size of the certificate chain (in DER). 413 totalSize = sizeof(SPDM_L1_CERTIFICATE_DER) + 414 sizeof(SPDM_L2_CERTIFICATE_DER) + 415 sizeof(SPDM_L3_CERTIFICATE_DER) + 416 secondCertSize + 417 firstCertSize; 418 419 remainingOutBufferSize = *outBufferSize; 420 if (remainingOutBufferSize < totalSize) 421 { 422 return NV_ERR_BUFFER_TOO_SMALL; 423 } 424 425 // 426 // Write the L1 DER certificate to the output buffer 427 // 428 pPortMemCopyStatus = portMemCopy(pOutBuffer, 429 remainingOutBufferSize, 430 SPDM_L1_CERTIFICATE_DER, 431 sizeof(SPDM_L1_CERTIFICATE_DER)); 432 if (pPortMemCopyStatus == NULL) 433 { 434 return NV_ERR_BUFFER_TOO_SMALL; 435 } 436 437 remainingOutBufferSize -= sizeof(SPDM_L1_CERTIFICATE_DER); 438 pOutBuffer += sizeof(SPDM_L1_CERTIFICATE_DER); 439 440 // 441 // Write the L2 DER certificate to the output buffer 442 // 443 pPortMemCopyStatus = portMemCopy(pOutBuffer, 444 remainingOutBufferSize, 445 SPDM_L2_CERTIFICATE_DER, 446 sizeof(SPDM_L2_CERTIFICATE_DER)); 447 if (pPortMemCopyStatus == NULL) 448 { 449 return NV_ERR_BUFFER_TOO_SMALL; 450 } 451 452 remainingOutBufferSize -= sizeof(SPDM_L2_CERTIFICATE_DER); 453 pOutBuffer += sizeof(SPDM_L2_CERTIFICATE_DER); 454 455 // 456 // Write the L3 DER certificate to the output buffer 457 // 458 pPortMemCopyStatus = portMemCopy(pOutBuffer, 459 remainingOutBufferSize, 460 SPDM_L3_CERTIFICATE_DER, 461 sizeof(SPDM_L3_CERTIFICATE_DER)); 462 if (pPortMemCopyStatus == NULL) 463 { 464 return NV_ERR_BUFFER_TOO_SMALL; 465 } 466 467 remainingOutBufferSize -= sizeof(SPDM_L3_CERTIFICATE_DER); 468 pOutBuffer += sizeof(SPDM_L3_CERTIFICATE_DER); 469 470 // 471 // Write the IK certificate in DER to the output buffer 472 // 473 pPortMemCopyStatus = portMemCopy(pOutBuffer, 474 remainingOutBufferSize, 475 pSecondCert, 476 secondCertSize); 477 if (pPortMemCopyStatus == NULL) 478 { 479 return NV_ERR_BUFFER_TOO_SMALL; 480 } 481 482 remainingOutBufferSize -= secondCertSize; 483 pOutBuffer += secondCertSize; 484 485 // 486 // Write the AK certificate in DER to the output buffer 487 // 488 pPortMemCopyStatus = portMemCopy(pOutBuffer, 489 remainingOutBufferSize, 490 pFirstCert, 491 firstCertSize); 492 if (pPortMemCopyStatus == NULL) 493 { 494 return NV_ERR_BUFFER_TOO_SMALL; 495 } 496 497 remainingOutBufferSize -= firstCertSize; 498 pOutBuffer += firstCertSize; 499 500 // Output the total certificate chain size 501 *outBufferSize = totalSize; 502 503 return NV_OK; 504 } 505 506 /*! 507 * Static function that first converts the IK and AK certificates from DER to 508 * PEM format. Then it builds the cert chain in PEM format. It is assumed that 509 * the all the certificates are valid. Also it is assumed that there is a valid 510 * spdm session already established. 511 */ 512 static NV_STATUS 513 _spdmBuildCertChainPem 514 ( 515 NvU8 *pFirstCert, 516 NvU32 firstCertSize, 517 NvU8 *pSecondCert, 518 NvU32 secondCertSize, 519 NvU8 *pOutBuffer, 520 size_t *outBufferSize 521 ) 522 { 523 NvU64 firstCertOutputSize = 0; 524 NvU64 secondCertOutputSize = 0; 525 NvU64 remainingOutBufferSize = 0; 526 void *pPortMemCopyStatus = NULL; 527 NV_STATUS status; 528 529 if (pFirstCert == NULL || pSecondCert == NULL || pOutBuffer == NULL || outBufferSize == NULL) 530 { 531 return NV_ERR_INVALID_ARGUMENT; 532 } 533 534 remainingOutBufferSize = *outBufferSize; 535 536 // 537 // Write the AK certificate to the output buffer 538 // 539 status = pem_write_buffer(pFirstCert, firstCertSize, pOutBuffer, 540 remainingOutBufferSize, &firstCertOutputSize); 541 if (status != NV_OK) 542 { 543 return status; 544 } 545 546 // 547 // Keep track how much space we have left in the output buffer 548 // and where the next certificate should start. 549 // Clear the last byte (NULL). 550 // 551 remainingOutBufferSize -= firstCertOutputSize - 1; 552 pOutBuffer += firstCertOutputSize - 1; 553 554 // 555 // Write the IK certificate to the output buffer 556 // 557 status = pem_write_buffer(pSecondCert, secondCertSize, pOutBuffer, 558 remainingOutBufferSize, &secondCertOutputSize); 559 if (status != NV_OK) 560 { 561 return status; 562 } 563 564 remainingOutBufferSize -= secondCertOutputSize - 1; 565 pOutBuffer += secondCertOutputSize - 1; 566 567 // Checking if the available size of buffer is enough to keep the whole 568 // certificate chain otherwise raise error. 569 if (remainingOutBufferSize < sizeof(SPDM_L1_CERTIFICATE_PEM) 570 + sizeof(SPDM_L2_CERTIFICATE_PEM) 571 + sizeof(SPDM_L3_CERTIFICATE_PEM)) 572 { 573 return NV_ERR_BUFFER_TOO_SMALL; 574 } 575 576 // 577 // Write the L3 certificate to the output buffer 578 // 579 pPortMemCopyStatus = portMemCopy(pOutBuffer, 580 remainingOutBufferSize, 581 SPDM_L3_CERTIFICATE_PEM, 582 sizeof(SPDM_L3_CERTIFICATE_PEM) - 1); 583 if (pPortMemCopyStatus == NULL) 584 { 585 return NV_ERR_BUFFER_TOO_SMALL; 586 } 587 588 remainingOutBufferSize -= sizeof(SPDM_L3_CERTIFICATE_PEM) - 1; 589 pOutBuffer += sizeof(SPDM_L3_CERTIFICATE_PEM) - 1; 590 591 // 592 // Write the L2 certificate to the output buffer 593 // 594 pPortMemCopyStatus = portMemCopy(pOutBuffer, 595 remainingOutBufferSize, 596 SPDM_L2_CERTIFICATE_PEM, 597 sizeof(SPDM_L2_CERTIFICATE_PEM) - 1); 598 if (pPortMemCopyStatus == NULL) 599 { 600 return NV_ERR_BUFFER_TOO_SMALL; 601 } 602 remainingOutBufferSize -= sizeof(SPDM_L2_CERTIFICATE_PEM) - 1; 603 pOutBuffer += sizeof(SPDM_L2_CERTIFICATE_PEM) - 1; 604 605 // 606 // Write the L1 certificate to the output buffer 607 // 608 pPortMemCopyStatus = portMemCopy(pOutBuffer, 609 remainingOutBufferSize, 610 SPDM_L1_CERTIFICATE_PEM, 611 sizeof(SPDM_L1_CERTIFICATE_PEM) - 1); 612 if (pPortMemCopyStatus == NULL) 613 { 614 return NV_ERR_BUFFER_TOO_SMALL; 615 } 616 617 // 618 // Output the total certificate chain size 619 // Do not count the NULL bytes. 620 // 621 *outBufferSize = firstCertOutputSize - 1 + 622 secondCertOutputSize - 1 + 623 sizeof(SPDM_L3_CERTIFICATE_PEM) - 1 + 624 sizeof(SPDM_L2_CERTIFICATE_PEM) - 1 + 625 sizeof(SPDM_L1_CERTIFICATE_PEM) - 1; 626 627 return NV_OK; 628 } 629 630 /* ------------------------ Public Functions ------------------------------- */ 631 NV_STATUS 632 spdmGetCertificates_GH100 633 ( 634 OBJGPU *pGpu, 635 Spdm *pSpdm 636 ) 637 { 638 NV_STATUS status = NV_OK; 639 NvU8 *pIkCertificate = NULL; 640 NvU32 ikCertificateSize = 0; 641 NvU8 *pAkCertificate = NULL; 642 NvU32 akCertificateSize = 0; 643 NvU8 *pGpuCerts = NULL; 644 size_t gpuCertsSize = 0; 645 NvU8 *pDerCertChain = NULL; 646 size_t derCertChainSize = 0; 647 NvU8 *pSpdmCertChainBufferEnd = NULL; 648 libspdm_context_t *pContext = NULL; 649 uint32_t base_hash_algo = 0; 650 NvU32 totalSize = 0; 651 652 if (pGpu == NULL || pSpdm == NULL) 653 { 654 return NV_ERR_INVALID_ARGUMENT; 655 } 656 657 if (pSpdm->pLibspdmContext == NULL) 658 { 659 return NV_ERR_NOT_READY; 660 } 661 662 // Allocate buffer for certificates. 663 gpuCertsSize = LIBSPDM_MAX_CERT_CHAIN_SIZE; 664 pGpuCerts = portMemAllocNonPaged(gpuCertsSize); 665 derCertChainSize = SPDM_MAX_ENCODED_CERT_CHAIN_SIZE; 666 pDerCertChain = portMemAllocNonPaged(derCertChainSize); 667 pSpdm->attestationCertChainSize = SPDM_MAX_ENCODED_CERT_CHAIN_SIZE; 668 pSpdm->pAttestationCertChain = portMemAllocNonPaged(pSpdm->attestationCertChainSize); 669 670 // Ensure data was properly allocated. 671 if (pGpuCerts == NULL || pDerCertChain == NULL || pSpdm->pAttestationCertChain == NULL) 672 { 673 status = NV_ERR_NO_MEMORY; 674 goto ErrorExit; 675 } 676 677 portMemSet(pGpuCerts, 0, gpuCertsSize); 678 portMemSet(pDerCertChain, 0, derCertChainSize); 679 portMemSet(pSpdm->pAttestationCertChain, 0, pSpdm->attestationCertChainSize); 680 681 // We fetch Attestation cert chain only on Hopper. 682 CHECK_SPDM_STATUS(libspdm_get_certificate(pSpdm->pLibspdmContext, SPDM_CERT_DEFAULT_SLOT_ID, 683 &gpuCertsSize, pGpuCerts)); 684 685 // Now, append the root certificates to create the entire chain. 686 pContext = (libspdm_context_t *)pSpdm->pLibspdmContext; 687 688 // 689 // Skip over the certificate chain size, reserved size and the root hash 690 // pSpdmCertChainBufferEnd represents last valid byte for cert buffer. 691 // 692 pSpdmCertChainBufferEnd = pGpuCerts + gpuCertsSize - 1; 693 base_hash_algo = pContext->connection_info.algorithm.base_hash_algo; 694 pIkCertificate = (NvU8 *)pGpuCerts; 695 pIkCertificate += sizeof(spdm_cert_chain_t) + libspdm_get_hash_size(base_hash_algo); 696 697 // Calculate the size of the IK cert, and skip past it to get the AK cert. 698 status = _calcX509CertSize(pIkCertificate, pSpdmCertChainBufferEnd, &ikCertificateSize); 699 700 if (status != NV_OK) 701 { 702 goto ErrorExit; 703 } 704 705 pAkCertificate = (NvU8 *)pIkCertificate + ikCertificateSize; 706 707 // Calculate the size of the AK certificate. 708 status = _calcX509CertSize(pAkCertificate, pSpdmCertChainBufferEnd, &akCertificateSize); 709 if (status != NV_OK) 710 { 711 return status; 712 } 713 714 // Make sure we have calculated the size correctly. 715 if ((pAkCertificate + akCertificateSize - 1) != pSpdmCertChainBufferEnd) 716 { 717 return NV_ERR_BUFFER_TOO_SMALL; 718 } 719 720 // Retrieve the entire certificate chain in DER format in order to validate it. 721 status = _spdmBuildCertChainDer(pAkCertificate, akCertificateSize, 722 pIkCertificate, ikCertificateSize, 723 pDerCertChain, 724 &derCertChainSize); 725 726 if (status != NV_OK) 727 { 728 goto ErrorExit; 729 } 730 731 totalSize = sizeof(SPDM_L1_CERTIFICATE_DER) + 732 sizeof(SPDM_L2_CERTIFICATE_DER) + 733 sizeof(SPDM_L3_CERTIFICATE_DER) + 734 akCertificateSize + 735 ikCertificateSize; 736 737 if (derCertChainSize != totalSize) 738 { 739 NV_PRINTF(LEVEL_ERROR, " %s: derCertChainSize(%lu) != totalSize(0x%x) !! \n", 740 __FUNCTION__, derCertChainSize, totalSize); 741 742 // Something has gone quite wrong with our calculations. 743 status = NV_ERR_BUFFER_TOO_SMALL; 744 goto ErrorExit; 745 } 746 747 // Now, validate that the certificate chain is correctly signed. 748 if (!libspdm_x509_verify_cert_chain(pDerCertChain, sizeof(SPDM_L1_CERTIFICATE_DER), 749 pDerCertChain + sizeof(SPDM_L1_CERTIFICATE_DER), 750 derCertChainSize - sizeof(SPDM_L1_CERTIFICATE_DER))) 751 { 752 status = NV_ERR_INVALID_DATA; 753 goto ErrorExit; 754 } 755 756 // 757 // Now that the cert chain is valid, retrieve the cert chain in PEM format, 758 // as the Verifier can only parse PEM format. 759 // 760 status = _spdmBuildCertChainPem(pAkCertificate, akCertificateSize, 761 pIkCertificate, ikCertificateSize, 762 pSpdm->pAttestationCertChain, 763 &pSpdm->attestationCertChainSize); 764 if (status != NV_OK) 765 { 766 goto ErrorExit; 767 } 768 769 ErrorExit: 770 // 771 // In both success and failure we need to free these allocated buffers. 772 // portMemFree() will handle if they are NULL. On success, keep 773 // the local pAttestationCertChain buffer. 774 // 775 portMemFree(pGpuCerts); 776 portMemFree(pDerCertChain); 777 778 if (status != NV_OK) 779 { 780 // portMemFree() handles NULL. 781 portMemFree(pSpdm->pAttestationCertChain); 782 pSpdm->pAttestationCertChain = NULL; 783 pSpdm->attestationCertChainSize = 0; 784 } 785 786 return status; 787 } 788 789 NV_STATUS 790 spdmGetCertChains_GH100 791 ( 792 OBJGPU *pGpu, 793 Spdm *pSpdm, 794 void *pKeyExCertChain, 795 NvU32 *pKeyExCertChainSize, 796 void *pAttestationCertChain, 797 NvU32 *pAttestationCertChainSize 798 ) 799 { 800 if (pGpu == NULL || pSpdm == NULL || pAttestationCertChain == NULL || 801 pAttestationCertChainSize == NULL) 802 { 803 return NV_ERR_INVALID_ARGUMENT; 804 } 805 806 // Check that we're in a valid state. 807 if (pSpdm->pLibspdmContext == NULL || pSpdm->pAttestationCertChain == NULL || 808 pSpdm->attestationCertChainSize == 0) 809 { 810 return NV_ERR_NOT_READY; 811 } 812 813 // We only support Attestation certificates on Hopper. 814 if (pKeyExCertChainSize != NULL) 815 { 816 pKeyExCertChainSize = 0; 817 } 818 819 if (*pAttestationCertChainSize < pSpdm->attestationCertChainSize) 820 { 821 return NV_ERR_BUFFER_TOO_SMALL; 822 } 823 824 portMemCopy(pAttestationCertChain, *pAttestationCertChainSize, 825 pSpdm->pAttestationCertChain, pSpdm->attestationCertChainSize); 826 *pAttestationCertChainSize = pSpdm->attestationCertChainSize; 827 828 return NV_OK; 829 } 830