Files
open-gpu-kernel-modules/src/common/nvswitch/kernel/ls10/tnvl_ls10.c
Andy Ritger 5e52edb203 550.120
2024-09-20 12:40:39 -07:00

1267 lines
49 KiB
C

/*
* SPDX-FileCopyrightText: Copyright (c) 2023-2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
/* ------------------------ Includes --------------------------------------- */
#include "common_nvswitch.h"
#include "haldef_nvswitch.h"
#include "ls10/ls10.h"
#include "ls10/soe_ls10.h"
#include "nvswitch/ls10/dev_nvlsaw_ip.h"
#include "nvswitch/ls10/dev_nvlsaw_ip_addendum.h"
#include "nvswitch/ls10/dev_ctrl_ip.h"
#include "nvswitch/ls10/dev_ctrl_ip_addendum.h"
#include "nvswitch/ls10/dev_cpr_ip.h"
#include "nvswitch/ls10/dev_npg_ip.h"
#include "nvswitch/ls10/dev_fsp_pri.h"
#include "nvswitch/ls10/dev_soe_ip.h"
#include "nvswitch/ls10/ptop_discovery_ip.h"
#include "nvswitch/ls10/dev_minion_ip.h"
#include <stddef.h>
/* ------------------------ Macros ----------------------------------------- */
#define TNVL_MAX_CERT_CHAIN_SIZE (0x1000)
#define TNVL_MAX_ENCODED_CERT_CHAIN_SIZE (0x1400)
#define DER_LONG_FORM_LENGTH_FIELD_BIT (0x80)
#define DER_CERT_SIZE_FIELD_LENGTH (0x4)
#define TNVL_PEM_BEGIN_CERTIFICATE "-----BEGIN CERTIFICATE-----\n"
#define TNVL_PEM_END_CERTIFICATE "-----END CERTIFICATE-----\n"
#define TNVL_MAX_MEASUREMENT_SIZE (0x2000)
#define TNVL_L1_CERTIFICATE_PEM "-----BEGIN CERTIFICATE-----\n"\
"MIICCzCCAZCgAwIBAgIQLTZwscoQBBHB/sDoKgZbVDAKBggqhkjOPQQDAzA1MSIw\n"\
"IAYDVQQDDBlOVklESUEgRGV2aWNlIElkZW50aXR5IENBMQ8wDQYDVQQKDAZOVklE\n"\
"SUEwIBcNMjExMTA1MDAwMDAwWhgPOTk5OTEyMzEyMzU5NTlaMDUxIjAgBgNVBAMM\n"\
"GU5WSURJQSBEZXZpY2UgSWRlbnRpdHkgQ0ExDzANBgNVBAoMBk5WSURJQTB2MBAG\n"\
"ByqGSM49AgEGBSuBBAAiA2IABA5MFKM7+KViZljbQSlgfky/RRnEQScW9NDZF8SX\n"\
"gAW96r6u/Ve8ZggtcYpPi2BS4VFu6KfEIrhN6FcHG7WP05W+oM+hxj7nyA1r1jkB\n"\
"2Ry70YfThX3Ba1zOryOP+MJ9vaNjMGEwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8B\n"\
"Af8EBAMCAQYwHQYDVR0OBBYEFFeF/4PyY8xlfWi3Olv0jUrL+0lfMB8GA1UdIwQY\n"\
"MBaAFFeF/4PyY8xlfWi3Olv0jUrL+0lfMAoGCCqGSM49BAMDA2kAMGYCMQCPeFM3\n"\
"TASsKQVaT+8S0sO9u97PVGCpE9d/I42IT7k3UUOLSR/qvJynVOD1vQKVXf0CMQC+\n"\
"EY55WYoDBvs2wPAH1Gw4LbcwUN8QCff8bFmV4ZxjCRr4WXTLFHBKjbfneGSBWwA=\n"\
"-----END CERTIFICATE-----\n"
#define TNVL_L2_CERTIFICATE_PEM "-----BEGIN CERTIFICATE-----\n"\
"MIICijCCAhCgAwIBAgIQTCVe3jvQAb8/SjtgX8qJijAKBggqhkjOPQQDAzA1MSIw\n"\
"IAYDVQQDDBlOVklESUEgRGV2aWNlIElkZW50aXR5IENBMQ8wDQYDVQQKDAZOVklE\n"\
"SUEwIBcNMjIwMTEyMDAwMDAwWhgPOTk5OTEyMzEyMzU5NTlaMD0xHjAcBgNVBAMM\n"\
"FU5WSURJQSBHSDEwMCBJZGVudGl0eTEbMBkGA1UECgwSTlZJRElBIENvcnBvcmF0\n"\
"aW9uMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAE+pg+tDUuILlZILk5wg22YEJ9Oh6c\n"\
"yPcsv3IvgRWcV4LeZK1pTCoQDIplZ0E4qsLG3G04pxsbMhxbqkiz9pqlTV2rtuVg\n"\
"SmIqnSYkU1jWXsPS9oVLCGE8VRLl1JvqyOxUo4HaMIHXMA8GA1UdEwEB/wQFMAMB\n"\
"Af8wDgYDVR0PAQH/BAQDAgEGMDsGA1UdHwQ0MDIwMKAuoCyGKmh0dHA6Ly9jcmwu\n"\
"bmRpcy5udmlkaWEuY29tL2NybC9sMS1yb290LmNybDA3BggrBgEFBQcBAQQrMCkw\n"\
"JwYIKwYBBQUHMAGGG2h0dHA6Ly9vY3NwLm5kaXMubnZpZGlhLmNvbTAdBgNVHQ4E\n"\
"FgQUB0Kg6wOcgGB7oUFhmU2uJffCmx4wHwYDVR0jBBgwFoAUV4X/g/JjzGV9aLc6\n"\
"W/SNSsv7SV8wCgYIKoZIzj0EAwMDaAAwZQIxAPIQhnveFxYIrPzBqViT2I34SfS4\n"\
"JGWFnk/1UcdmgJmp+7l6rH/C4qxwntYSgeYrlQIwdjQuofHnhd1RL09OBO34566J\n"\
"C9bYAosT/86cCojiGjhLnal9hJOH0nS/lrbaoc5a\n"\
"-----END CERTIFICATE-----\n"
#define TNVL_L3_CERTIFICATE_PEM "-----BEGIN CERTIFICATE-----\n"\
"MIICqTCCAi+gAwIBAgIQcidIXMg4KYZ1y7ooFz5gUjAKBggqhkjOPQQDAzA9MR4w\n"\
"HAYDVQQDDBVOVklESUEgR0gxMDAgSWRlbnRpdHkxGzAZBgNVBAoMEk5WSURJQSBD\n"\
"b3Jwb3JhdGlvbjAgFw0yMjAzMDEwMDAwMDBaGA85OTk5MTIzMTIzNTk1OVowUzEn\n"\
"MCUGA1UEAwweTlZJRElBIExTXzEwIFByb3Zpc2lvbmVyIElDQSAxMRswGQYDVQQK\n"\
"DBJOVklESUEgQ29ycG9yYXRpb24xCzAJBgNVBAYTAlVTMHYwEAYHKoZIzj0CAQYF\n"\
"K4EEACIDYgAEyGbP8B2aF0Zd0V5GhWfcnC8K8BXUJMGPhAWQo88WymU0Az+u2Y7B\n"\
"zI9li0TyXhth18dB1yqodYgH3KKU1c0beV1OkAUvnlx3JpNPhx8nfdlhpM9jqsXG\n"\
"JXeJixW5+VOlo4HbMIHYMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEG\n"\
"MDwGA1UdHwQ1MDMwMaAvoC2GK2h0dHA6Ly9jcmwubmRpcy5udmlkaWEuY29tL2Ny\n"\
"bC9sMi1naDEwMC5jcmwwNwYIKwYBBQUHAQEEKzApMCcGCCsGAQUFBzABhhtodHRw\n"\
"Oi8vb2NzcC5uZGlzLm52aWRpYS5jb20wHQYDVR0OBBYEFBFA9xSZ0ALwvOeei4fR\n"\
"von435VEMB8GA1UdIwQYMBaAFAdCoOsDnIBge6FBYZlNriX3wpseMAoGCCqGSM49\n"\
"BAMDA2gAMGUCMQDWLHcBKxi9QVrfMoDcIg3gLBRe5oEo/Q4KR3WaUMz9ABxMHK9Y\n"\
"K4xPtjXW4Bup5FwCMBhLpTQqsly8gQ6w1CIyMEC4n/LSjM65TC4pGVokSyjpoyp0\n"\
"gWjuEBq1vBNs76Ge8A==\n"\
"-----END CERTIFICATE-----\n"
const static NvU8 TNVL_L1_CERTIFICATE_DER[527] =
{
0x30, 0x82, 0x02, 0x0b, 0x30, 0x82, 0x01, 0x90, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0x2d,
0x36, 0x70, 0xb1, 0xca, 0x10, 0x04, 0x11, 0xc1, 0xfe, 0xc0, 0xe8, 0x2a, 0x06, 0x5b, 0x54, 0x30,
0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x03, 0x30, 0x35, 0x31, 0x22, 0x30,
0x20, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x19, 0x4e, 0x56, 0x49, 0x44, 0x49, 0x41, 0x20, 0x44,
0x65, 0x76, 0x69, 0x63, 0x65, 0x20, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x20, 0x43,
0x41, 0x31, 0x0f, 0x30, 0x0d, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x06, 0x4e, 0x56, 0x49, 0x44,
0x49, 0x41, 0x30, 0x20, 0x17, 0x0d, 0x32, 0x31, 0x31, 0x31, 0x30, 0x35, 0x30, 0x30, 0x30, 0x30,
0x30, 0x30, 0x5a, 0x18, 0x0f, 0x39, 0x39, 0x39, 0x39, 0x31, 0x32, 0x33, 0x31, 0x32, 0x33, 0x35,
0x39, 0x35, 0x39, 0x5a, 0x30, 0x35, 0x31, 0x22, 0x30, 0x20, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c,
0x19, 0x4e, 0x56, 0x49, 0x44, 0x49, 0x41, 0x20, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x20, 0x49,
0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x20, 0x43, 0x41, 0x31, 0x0f, 0x30, 0x0d, 0x06, 0x03,
0x55, 0x04, 0x0a, 0x0c, 0x06, 0x4e, 0x56, 0x49, 0x44, 0x49, 0x41, 0x30, 0x76, 0x30, 0x10, 0x06,
0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x22, 0x03,
0x62, 0x00, 0x04, 0x0e, 0x4c, 0x14, 0xa3, 0x3b, 0xf8, 0xa5, 0x62, 0x66, 0x58, 0xdb, 0x41, 0x29,
0x60, 0x7e, 0x4c, 0xbf, 0x45, 0x19, 0xc4, 0x41, 0x27, 0x16, 0xf4, 0xd0, 0xd9, 0x17, 0xc4, 0x97,
0x80, 0x05, 0xbd, 0xea, 0xbe, 0xae, 0xfd, 0x57, 0xbc, 0x66, 0x08, 0x2d, 0x71, 0x8a, 0x4f, 0x8b,
0x60, 0x52, 0xe1, 0x51, 0x6e, 0xe8, 0xa7, 0xc4, 0x22, 0xb8, 0x4d, 0xe8, 0x57, 0x07, 0x1b, 0xb5,
0x8f, 0xd3, 0x95, 0xbe, 0xa0, 0xcf, 0xa1, 0xc6, 0x3e, 0xe7, 0xc8, 0x0d, 0x6b, 0xd6, 0x39, 0x01,
0xd9, 0x1c, 0xbb, 0xd1, 0x87, 0xd3, 0x85, 0x7d, 0xc1, 0x6b, 0x5c, 0xce, 0xaf, 0x23, 0x8f, 0xf8,
0xc2, 0x7d, 0xbd, 0xa3, 0x63, 0x30, 0x61, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01,
0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01,
0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04,
0x16, 0x04, 0x14, 0x57, 0x85, 0xff, 0x83, 0xf2, 0x63, 0xcc, 0x65, 0x7d, 0x68, 0xb7, 0x3a, 0x5b,
0xf4, 0x8d, 0x4a, 0xcb, 0xfb, 0x49, 0x5f, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18,
0x30, 0x16, 0x80, 0x14, 0x57, 0x85, 0xff, 0x83, 0xf2, 0x63, 0xcc, 0x65, 0x7d, 0x68, 0xb7, 0x3a,
0x5b, 0xf4, 0x8d, 0x4a, 0xcb, 0xfb, 0x49, 0x5f, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce,
0x3d, 0x04, 0x03, 0x03, 0x03, 0x69, 0x00, 0x30, 0x66, 0x02, 0x31, 0x00, 0x8f, 0x78, 0x53, 0x37,
0x4c, 0x04, 0xac, 0x29, 0x05, 0x5a, 0x4f, 0xef, 0x12, 0xd2, 0xc3, 0xbd, 0xbb, 0xde, 0xcf, 0x54,
0x60, 0xa9, 0x13, 0xd7, 0x7f, 0x23, 0x8d, 0x88, 0x4f, 0xb9, 0x37, 0x51, 0x43, 0x8b, 0x49, 0x1f,
0xea, 0xbc, 0x9c, 0xa7, 0x54, 0xe0, 0xf5, 0xbd, 0x02, 0x95, 0x5d, 0xfd, 0x02, 0x31, 0x00, 0xbe,
0x11, 0x8e, 0x79, 0x59, 0x8a, 0x03, 0x06, 0xfb, 0x36, 0xc0, 0xf0, 0x07, 0xd4, 0x6c, 0x38, 0x2d,
0xb7, 0x30, 0x50, 0xdf, 0x10, 0x09, 0xf7, 0xfc, 0x6c, 0x59, 0x95, 0xe1, 0x9c, 0x63, 0x09, 0x1a,
0xf8, 0x59, 0x74, 0xcb, 0x14, 0x70, 0x4a, 0x8d, 0xb7, 0xe7, 0x78, 0x64, 0x81, 0x5b, 0x00
};
const static NvU8 TNVL_L2_CERTIFICATE_DER[654] =
{
0x30, 0x82, 0x02, 0x8a, 0x30, 0x82, 0x02, 0x10, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0x4c,
0x25, 0x5e, 0xde, 0x3b, 0xd0, 0x01, 0xbf, 0x3f, 0x4a, 0x3b, 0x60, 0x5f, 0xca, 0x89, 0x8a, 0x30,
0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x03, 0x30, 0x35, 0x31, 0x22, 0x30,
0x20, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x19, 0x4e, 0x56, 0x49, 0x44, 0x49, 0x41, 0x20, 0x44,
0x65, 0x76, 0x69, 0x63, 0x65, 0x20, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x20, 0x43,
0x41, 0x31, 0x0f, 0x30, 0x0d, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x06, 0x4e, 0x56, 0x49, 0x44,
0x49, 0x41, 0x30, 0x20, 0x17, 0x0d, 0x32, 0x32, 0x30, 0x31, 0x31, 0x32, 0x30, 0x30, 0x30, 0x30,
0x30, 0x30, 0x5a, 0x18, 0x0f, 0x39, 0x39, 0x39, 0x39, 0x31, 0x32, 0x33, 0x31, 0x32, 0x33, 0x35,
0x39, 0x35, 0x39, 0x5a, 0x30, 0x3d, 0x31, 0x1e, 0x30, 0x1c, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c,
0x15, 0x4e, 0x56, 0x49, 0x44, 0x49, 0x41, 0x20, 0x47, 0x48, 0x31, 0x30, 0x30, 0x20, 0x49, 0x64,
0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x31, 0x1b, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c,
0x12, 0x4e, 0x56, 0x49, 0x44, 0x49, 0x41, 0x20, 0x43, 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61, 0x74,
0x69, 0x6f, 0x6e, 0x30, 0x76, 0x30, 0x10, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01,
0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x22, 0x03, 0x62, 0x00, 0x04, 0xfa, 0x98, 0x3e, 0xb4, 0x35,
0x2e, 0x20, 0xb9, 0x59, 0x20, 0xb9, 0x39, 0xc2, 0x0d, 0xb6, 0x60, 0x42, 0x7d, 0x3a, 0x1e, 0x9c,
0xc8, 0xf7, 0x2c, 0xbf, 0x72, 0x2f, 0x81, 0x15, 0x9c, 0x57, 0x82, 0xde, 0x64, 0xad, 0x69, 0x4c,
0x2a, 0x10, 0x0c, 0x8a, 0x65, 0x67, 0x41, 0x38, 0xaa, 0xc2, 0xc6, 0xdc, 0x6d, 0x38, 0xa7, 0x1b,
0x1b, 0x32, 0x1c, 0x5b, 0xaa, 0x48, 0xb3, 0xf6, 0x9a, 0xa5, 0x4d, 0x5d, 0xab, 0xb6, 0xe5, 0x60,
0x4a, 0x62, 0x2a, 0x9d, 0x26, 0x24, 0x53, 0x58, 0xd6, 0x5e, 0xc3, 0xd2, 0xf6, 0x85, 0x4b, 0x08,
0x61, 0x3c, 0x55, 0x12, 0xe5, 0xd4, 0x9b, 0xea, 0xc8, 0xec, 0x54, 0xa3, 0x81, 0xda, 0x30, 0x81,
0xd7, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01,
0x01, 0xff, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02,
0x01, 0x06, 0x30, 0x3b, 0x06, 0x03, 0x55, 0x1d, 0x1f, 0x04, 0x34, 0x30, 0x32, 0x30, 0x30, 0xa0,
0x2e, 0xa0, 0x2c, 0x86, 0x2a, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x72, 0x6c, 0x2e,
0x6e, 0x64, 0x69, 0x73, 0x2e, 0x6e, 0x76, 0x69, 0x64, 0x69, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x2f,
0x63, 0x72, 0x6c, 0x2f, 0x6c, 0x31, 0x2d, 0x72, 0x6f, 0x6f, 0x74, 0x2e, 0x63, 0x72, 0x6c, 0x30,
0x37, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x01, 0x01, 0x04, 0x2b, 0x30, 0x29, 0x30,
0x27, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x86, 0x1b, 0x68, 0x74, 0x74,
0x70, 0x3a, 0x2f, 0x2f, 0x6f, 0x63, 0x73, 0x70, 0x2e, 0x6e, 0x64, 0x69, 0x73, 0x2e, 0x6e, 0x76,
0x69, 0x64, 0x69, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04,
0x16, 0x04, 0x14, 0x07, 0x42, 0xa0, 0xeb, 0x03, 0x9c, 0x80, 0x60, 0x7b, 0xa1, 0x41, 0x61, 0x99,
0x4d, 0xae, 0x25, 0xf7, 0xc2, 0x9b, 0x1e, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18,
0x30, 0x16, 0x80, 0x14, 0x57, 0x85, 0xff, 0x83, 0xf2, 0x63, 0xcc, 0x65, 0x7d, 0x68, 0xb7, 0x3a,
0x5b, 0xf4, 0x8d, 0x4a, 0xcb, 0xfb, 0x49, 0x5f, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce,
0x3d, 0x04, 0x03, 0x03, 0x03, 0x68, 0x00, 0x30, 0x65, 0x02, 0x31, 0x00, 0xf2, 0x10, 0x86, 0x7b,
0xde, 0x17, 0x16, 0x08, 0xac, 0xfc, 0xc1, 0xa9, 0x58, 0x93, 0xd8, 0x8d, 0xf8, 0x49, 0xf4, 0xb8,
0x24, 0x65, 0x85, 0x9e, 0x4f, 0xf5, 0x51, 0xc7, 0x66, 0x80, 0x99, 0xa9, 0xfb, 0xb9, 0x7a, 0xac,
0x7f, 0xc2, 0xe2, 0xac, 0x70, 0x9e, 0xd6, 0x12, 0x81, 0xe6, 0x2b, 0x95, 0x02, 0x30, 0x76, 0x34,
0x2e, 0xa1, 0xf1, 0xe7, 0x85, 0xdd, 0x51, 0x2f, 0x4f, 0x4e, 0x04, 0xed, 0xf8, 0xe7, 0xae, 0x89,
0x0b, 0xd6, 0xd8, 0x02, 0x8b, 0x13, 0xff, 0xce, 0x9c, 0x0a, 0x88, 0xe2, 0x1a, 0x38, 0x4b, 0x9d,
0xa9, 0x7d, 0x84, 0x93, 0x87, 0xd2, 0x74, 0xbf, 0x96, 0xb6, 0xda, 0xa1, 0xce, 0x5a,
};
const static NvU8 TNVL_L3_CERTIFICATE_DER[686] =
{
0x30, 0x82, 0x02, 0xaa, 0x30, 0x82, 0x02, 0x2f, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0x6a,
0xfe, 0x71, 0x84, 0xf9, 0x22, 0x32, 0xc8, 0xdf, 0x7b, 0x24, 0x22, 0x61, 0x77, 0x6e, 0x56, 0x30,
0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x03, 0x30, 0x3d, 0x31, 0x1e, 0x30,
0x1c, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x15, 0x4e, 0x56, 0x49, 0x44, 0x49, 0x41, 0x20, 0x47,
0x48, 0x31, 0x30, 0x30, 0x20, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x31, 0x1b, 0x30,
0x19, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x12, 0x4e, 0x56, 0x49, 0x44, 0x49, 0x41, 0x20, 0x43,
0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x30, 0x20, 0x17, 0x0d, 0x32, 0x32,
0x30, 0x33, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x39, 0x39, 0x39,
0x39, 0x31, 0x32, 0x33, 0x31, 0x32, 0x33, 0x35, 0x39, 0x35, 0x39, 0x5a, 0x30, 0x53, 0x31, 0x27,
0x30, 0x25, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x1e, 0x4e, 0x56, 0x49, 0x44, 0x49, 0x41, 0x20,
0x47, 0x48, 0x31, 0x30, 0x30, 0x20, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65,
0x72, 0x20, 0x49, 0x43, 0x41, 0x20, 0x31, 0x31, 0x1b, 0x30, 0x19, 0x06, 0x03, 0x55, 0x04, 0x0a,
0x0c, 0x12, 0x4e, 0x56, 0x49, 0x44, 0x49, 0x41, 0x20, 0x43, 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61,
0x74, 0x69, 0x6f, 0x6e, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55,
0x53, 0x30, 0x76, 0x30, 0x10, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x05,
0x2b, 0x81, 0x04, 0x00, 0x22, 0x03, 0x62, 0x00, 0x04, 0xcd, 0x47, 0x56, 0xaa, 0x39, 0xf5, 0x3a,
0x55, 0xe1, 0x2d, 0xf1, 0x4e, 0x28, 0x01, 0x53, 0x82, 0x1a, 0x86, 0xf9, 0x0d, 0xf3, 0x17, 0x8c,
0x60, 0x48, 0x16, 0xd9, 0xb1, 0x41, 0x32, 0x59, 0x80, 0x82, 0xde, 0xb2, 0xa3, 0x13, 0xd3, 0x67,
0xa3, 0xcf, 0x19, 0xa4, 0x14, 0x31, 0xf3, 0x93, 0xa8, 0xd0, 0xf9, 0x2a, 0x3f, 0x67, 0x70, 0xa0,
0xc5, 0x4d, 0x4d, 0x03, 0x2f, 0xe5, 0xcb, 0xf2, 0xf6, 0x32, 0xda, 0x4e, 0xf4, 0x93, 0x5d, 0x9c,
0x0d, 0xd8, 0x74, 0x07, 0x13, 0xdb, 0xbb, 0xc7, 0xb0, 0x48, 0x62, 0xb5, 0xa2, 0xd2, 0xc1, 0xb7,
0xe6, 0xad, 0x48, 0x24, 0xd4, 0x8e, 0x18, 0xee, 0x4b, 0xa3, 0x81, 0xdb, 0x30, 0x81, 0xd8, 0x30,
0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff,
0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06,
0x30, 0x3c, 0x06, 0x03, 0x55, 0x1d, 0x1f, 0x04, 0x35, 0x30, 0x33, 0x30, 0x31, 0xa0, 0x2f, 0xa0,
0x2d, 0x86, 0x2b, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x63, 0x72, 0x6c, 0x2e, 0x6e, 0x64,
0x69, 0x73, 0x2e, 0x6e, 0x76, 0x69, 0x64, 0x69, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x72,
0x6c, 0x2f, 0x6c, 0x32, 0x2d, 0x67, 0x68, 0x31, 0x30, 0x30, 0x2e, 0x63, 0x72, 0x6c, 0x30, 0x37,
0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x01, 0x01, 0x04, 0x2b, 0x30, 0x29, 0x30, 0x27,
0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x86, 0x1b, 0x68, 0x74, 0x74, 0x70,
0x3a, 0x2f, 0x2f, 0x6f, 0x63, 0x73, 0x70, 0x2e, 0x6e, 0x64, 0x69, 0x73, 0x2e, 0x6e, 0x76, 0x69,
0x64, 0x69, 0x61, 0x2e, 0x63, 0x6f, 0x6d, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16,
0x04, 0x14, 0x29, 0x68, 0xcb, 0x16, 0x2c, 0xd0, 0x77, 0x95, 0x72, 0xa2, 0x79, 0x10, 0x03, 0xe6,
0x9e, 0xba, 0x0c, 0xcc, 0x0a, 0x94, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30,
0x16, 0x80, 0x14, 0x07, 0x42, 0xa0, 0xeb, 0x03, 0x9c, 0x80, 0x60, 0x7b, 0xa1, 0x41, 0x61, 0x99,
0x4d, 0xae, 0x25, 0xf7, 0xc2, 0x9b, 0x1e, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d,
0x04, 0x03, 0x03, 0x03, 0x69, 0x00, 0x30, 0x66, 0x02, 0x31, 0x00, 0xca, 0xd0, 0x10, 0xab, 0xe3,
0xd0, 0xcd, 0x27, 0x8f, 0x18, 0x87, 0x9c, 0x2e, 0xdf, 0xcf, 0x1b, 0x66, 0x27, 0xc3, 0x17, 0x10,
0x2c, 0x89, 0x44, 0xb8, 0x53, 0x57, 0xc6, 0x9a, 0x92, 0x59, 0x16, 0x10, 0x9b, 0x38, 0x31, 0xfa,
0x99, 0x1c, 0x1c, 0x33, 0x1a, 0x7a, 0x10, 0xe6, 0xb2, 0x66, 0xe6, 0x02, 0x31, 0x00, 0xd8, 0x29,
0x3c, 0x8d, 0x73, 0x61, 0x71, 0x58, 0x5b, 0xa1, 0x1e, 0xd7, 0x42, 0x13, 0x79, 0x6c, 0xe1, 0x2e,
0xd2, 0x22, 0x77, 0xa1, 0x74, 0x4a, 0xd3, 0x64, 0xdb, 0xa1, 0x17, 0x29, 0x9c, 0xe1, 0x83, 0x8c,
0xe9, 0x59, 0x4b, 0x59, 0x36, 0x3f, 0x08, 0xcf, 0xab, 0x7a, 0xc8, 0xe3, 0xab, 0x14,
};
/* ------------------------ Static Functions ------------------------------- */
/*!
@param pCert : The pointer to certification chain start
@param bufferEnd : The pointer to certification chain end
@parsm pCertLength : The pointer to store return certification size
@return Return NV-OK if no error.
* Static function that calculates the length of the X509 certificate in DER/TLV
* format. It assumes that the certificate is valid.
*/
static NvlStatus
_calc_x509_cert_size_ls10
(
nvswitch_device *device,
NvU8 *pCert,
NvU8 *bufferEnd,
NvU32 *pCertLength
)
{
// The cert is in TLV format.
NvU32 certSize = pCert[1];
// Check to make sure that some data exists after TNVL header, and it is enough to check cert size.
if (pCert + DER_CERT_SIZE_FIELD_LENGTH >= bufferEnd ||
pCert + DER_CERT_SIZE_FIELD_LENGTH <= pCert)
{
NVSWITCH_PRINT(device, ERROR,
"%s: pCert + DER_CERT_SIZE_FIELD_LENGTH(0x%x) is not valid value !! \n",
__FUNCTION__, DER_CERT_SIZE_FIELD_LENGTH);
return -NVL_NO_MEM;
}
// Check if the length is in DER longform.
// MSB in the length field is set for long form notation.
// fields.
if (certSize & DER_LONG_FORM_LENGTH_FIELD_BIT)
{
//
// The remaining bits in the length field indicate the
// number of following bytes used to represent the length.
// in base 256, most significant digit first.
//
NvU32 numLenBytes = certSize & 0x3f;
NvU8 *pStart = &pCert[2];
NvU8 *pEnd = pStart + numLenBytes; // NOTE: Don't need to subtract numLenBytes 1 here.
// Checking for buffer overflow.
if (pEnd > bufferEnd)
{
return -NVL_NO_MEM;
}
certSize = *pStart;
while (++pStart < pEnd)
{
certSize = (certSize << 8) + *pStart ;
}
// Total cert length includes the Tag + length
// Adding it here.
certSize += 2 + numLenBytes;
}
//
// Check to make sure we have not hit end of buffer, and there is space for AK cert.
// Check for underflow as well. This makes sure we haven't missed the calculation to
// go past the end of the buffer
//
if (pCert + (certSize - 1) > bufferEnd ||
pCert + (certSize - 1) <= pCert)
{
NVSWITCH_PRINT(device, ERROR,
"%s: pCert + (certSize(0x%x) - 1) is not a valid value !! \n",
__FUNCTION__, certSize);
return -NVL_NO_MEM;
}
*pCertLength = certSize;
return NVL_SUCCESS;
}
static NvlStatus
_pem_write_buffer_ls10
(
nvswitch_device *device,
NvU8 const *der,
NvU64 derLen,
NvU8 *buffer,
NvU64 bufferLen,
NvU64 *bufferUsed
)
{
static const NvU8 base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
NvU64 i, tmp, size;
NvU64 printed = 0;
NvU8 *ptr = buffer;
// Base64 encoded size
size = (derLen + 2) / 3 * 4;
// Add 1 byte per 64 for newline
size = size + (size + 63) / 64;
// Add header excluding the terminating null and footer including the null
size += sizeof(TNVL_PEM_BEGIN_CERTIFICATE) - 1 +
sizeof(TNVL_PEM_END_CERTIFICATE);
if (bufferLen < size)
{
return -NVL_NO_MEM;
}
nvswitch_os_memcpy(ptr, TNVL_PEM_BEGIN_CERTIFICATE, sizeof(TNVL_PEM_BEGIN_CERTIFICATE) - 1);
ptr += sizeof(TNVL_PEM_BEGIN_CERTIFICATE) - 1;
for (i = 0; (i + 2) < derLen; i += 3)
{
tmp = (der[i] << 16) | (der[i + 1] << 8) | (der[i + 2]);
*ptr++ = base64[(tmp >> 18) & 63];
*ptr++ = base64[(tmp >> 12) & 63];
*ptr++ = base64[(tmp >> 6) & 63];
*ptr++ = base64[(tmp >> 0) & 63];
printed += 4;
if (printed == 64)
{
*ptr++ = '\n';
printed = 0;
}
}
if ((i == derLen) && (printed != 0))
{
*ptr++ = '\n';
}
// 1 byte extra
if (i == (derLen - 1))
{
tmp = der[i] << 4;
*ptr++ = base64[(tmp >> 6) & 63];
*ptr++ = base64[(tmp >> 0) & 63];
*ptr++ = '=';
*ptr++ = '=';
*ptr++ = '\n';
}
// 2 byte extra
if (i == (derLen - 2))
{
tmp = ((der[i] << 8) | (der[i + 1])) << 2;
*ptr++ = base64[(tmp >> 12) & 63];
*ptr++ = base64[(tmp >> 6) & 63];
*ptr++ = base64[(tmp >> 0) & 63];
*ptr++ = '=';
*ptr++ = '\n';
}
nvswitch_os_memcpy(ptr, TNVL_PEM_END_CERTIFICATE, sizeof(TNVL_PEM_END_CERTIFICATE));
ptr += sizeof(TNVL_PEM_END_CERTIFICATE);
*bufferUsed = size;
return NVL_SUCCESS;
}
/*!
* Static function builds the cert chain in DER format. It is assumed that
* the all the certificates are valid. Also it is assumed that there is a valid
* tnvl session already established.
*/
static NvlStatus
_tnvl_build_cert_chain_der_ls10
(
nvswitch_device *device,
NvU8 *pFirstCert,
NvU32 firstCertSize,
NvU8 *pSecondCert,
NvU32 secondCertSize,
NvU8 *pOutBuffer,
size_t *outBufferSize
)
{
NvU64 remainingOutBufferSize = 0;
NvU64 totalSize = 0;
void *pPortMemCopyStatus = NULL;
if (pFirstCert == NULL || pSecondCert == NULL || pOutBuffer == NULL || outBufferSize == NULL)
{
return -NVL_BAD_ARGS;
}
// Calculate the total size of the certificate chain (in DER).
totalSize = sizeof(TNVL_L1_CERTIFICATE_DER) +
sizeof(TNVL_L2_CERTIFICATE_DER) +
sizeof(TNVL_L3_CERTIFICATE_DER) +
secondCertSize +
firstCertSize;
remainingOutBufferSize = *outBufferSize;
if (remainingOutBufferSize < totalSize)
{
return -NVL_NO_MEM;
}
//
// Write the L1 DER certificate to the output buffer
//
pPortMemCopyStatus = nvswitch_os_memcpy(pOutBuffer,
TNVL_L1_CERTIFICATE_DER,
sizeof(TNVL_L1_CERTIFICATE_DER));
if (pPortMemCopyStatus == NULL)
{
return -NVL_NO_MEM;
}
remainingOutBufferSize -= sizeof(TNVL_L1_CERTIFICATE_DER);
pOutBuffer += sizeof(TNVL_L1_CERTIFICATE_DER);
//
// Write the L2 DER certificate to the output buffer
//
pPortMemCopyStatus = nvswitch_os_memcpy(pOutBuffer,
TNVL_L2_CERTIFICATE_DER,
sizeof(TNVL_L2_CERTIFICATE_DER));
if (pPortMemCopyStatus == NULL)
{
return -NVL_NO_MEM;
}
remainingOutBufferSize -= sizeof(TNVL_L2_CERTIFICATE_DER);
pOutBuffer += sizeof(TNVL_L2_CERTIFICATE_DER);
//
// Write the L3 DER certificate to the output buffer
//
pPortMemCopyStatus = nvswitch_os_memcpy(pOutBuffer,
TNVL_L3_CERTIFICATE_DER,
sizeof(TNVL_L3_CERTIFICATE_DER));
if (pPortMemCopyStatus == NULL)
{
return -NVL_NO_MEM;
}
remainingOutBufferSize -= sizeof(TNVL_L3_CERTIFICATE_DER);
pOutBuffer += sizeof(TNVL_L3_CERTIFICATE_DER);
//
// Write the IK certificate in DER to the output buffer
//
pPortMemCopyStatus = nvswitch_os_memcpy(pOutBuffer,
pSecondCert,
secondCertSize);
if (pPortMemCopyStatus == NULL)
{
return -NVL_NO_MEM;
}
remainingOutBufferSize -= secondCertSize;
pOutBuffer += secondCertSize;
//
// Write the AK certificate in DER to the output buffer
//
pPortMemCopyStatus = nvswitch_os_memcpy(pOutBuffer,
pFirstCert,
firstCertSize);
if (pPortMemCopyStatus == NULL)
{
return -NVL_NO_MEM;
}
remainingOutBufferSize -= firstCertSize;
pOutBuffer += firstCertSize;
// Output the total certificate chain size
*outBufferSize = totalSize;
return NVL_SUCCESS;
}
/*!
* Static function that first converts the IK and AK certificates from DER to
* PEM format. Then it builds the cert chain in PEM format. It is assumed that
* the all the certificates are valid. Also it is assumed that there is a valid
* tnvl session already established.
*/
static NvlStatus
_tnvl_build_cert_chain_pem_ls10
(
nvswitch_device *device,
NvU8 *pFirstCert,
NvU32 firstCertSize,
NvU8 *pSecondCert,
NvU32 secondCertSize,
NvU8 *pOutBuffer,
size_t *outBufferSize
)
{
NvU64 firstCertOutputSize = 0;
NvU64 secondCertOutputSize = 0;
NvU64 remainingOutBufferSize = 0;
void *pPortMemCopyStatus = NULL;
NvlStatus status;
if (pFirstCert == NULL || pSecondCert == NULL || pOutBuffer == NULL || outBufferSize == NULL)
{
return -NVL_BAD_ARGS;
}
remainingOutBufferSize = *outBufferSize;
//
// Write the AK certificate to the output buffer
//
status = _pem_write_buffer_ls10(device, pFirstCert, firstCertSize, pOutBuffer,
remainingOutBufferSize, &firstCertOutputSize);
if (status != NVL_SUCCESS)
{
return status;
}
//
// Keep track how much space we have left in the output buffer
// and where the next certificate should start.
// Clear the last byte (NULL).
//
remainingOutBufferSize -= firstCertOutputSize - 1;
pOutBuffer += firstCertOutputSize - 1;
//
// Write the IK certificate to the output buffer
//
status = _pem_write_buffer_ls10(device, pSecondCert, secondCertSize, pOutBuffer,
remainingOutBufferSize, &secondCertOutputSize);
if (status != NVL_SUCCESS)
{
return status;
}
remainingOutBufferSize -= secondCertOutputSize - 1;
pOutBuffer += secondCertOutputSize - 1;
// Checking if the available size of buffer is enough to keep the whole
// certificate chain otherwise raise error.
if (remainingOutBufferSize < sizeof(TNVL_L1_CERTIFICATE_PEM)
+ sizeof(TNVL_L2_CERTIFICATE_PEM)
+ sizeof(TNVL_L3_CERTIFICATE_PEM))
{
return -NVL_NO_MEM;
}
//
// Write the L3 certificate to the output buffer
//
pPortMemCopyStatus = nvswitch_os_memcpy(pOutBuffer,
TNVL_L3_CERTIFICATE_PEM,
sizeof(TNVL_L3_CERTIFICATE_PEM) - 1);
if (pPortMemCopyStatus == NULL)
{
return -NVL_NO_MEM;
}
remainingOutBufferSize -= sizeof(TNVL_L3_CERTIFICATE_PEM) - 1;
pOutBuffer += sizeof(TNVL_L3_CERTIFICATE_PEM) - 1;
//
// Write the L2 certificate to the output buffer
//
pPortMemCopyStatus = nvswitch_os_memcpy(pOutBuffer,
TNVL_L2_CERTIFICATE_PEM,
sizeof(TNVL_L2_CERTIFICATE_PEM) - 1);
if (pPortMemCopyStatus == NULL)
{
return -NVL_NO_MEM;
}
remainingOutBufferSize -= sizeof(TNVL_L2_CERTIFICATE_PEM) - 1;
pOutBuffer += sizeof(TNVL_L2_CERTIFICATE_PEM) - 1;
//
// Write the L1 certificate to the output buffer
//
pPortMemCopyStatus = nvswitch_os_memcpy(pOutBuffer,
TNVL_L1_CERTIFICATE_PEM,
sizeof(TNVL_L1_CERTIFICATE_PEM) - 1);
if (pPortMemCopyStatus == NULL)
{
return -NVL_NO_MEM;
}
//
// Output the total certificate chain size
// Do not count the NULL bytes.
//
*outBufferSize = firstCertOutputSize - 1 +
secondCertOutputSize - 1 +
sizeof(TNVL_L3_CERTIFICATE_PEM) - 1 +
sizeof(TNVL_L2_CERTIFICATE_PEM) - 1 +
sizeof(TNVL_L1_CERTIFICATE_PEM) - 1;
return NVL_SUCCESS;
}
/* ------------------------ Public Functions ------------------------------- */
static NvlStatus
_nvswitch_tnvl_get_cert_chain_from_fsp_ls10
(
nvswitch_device *device,
NvU8 *pCertChain,
size_t *pCertChainLength
)
{
NvlStatus status;
TNVL_GET_ATT_CERTS_CMD_PAYLOAD *pCmdPayload = nvswitch_os_malloc(sizeof(TNVL_GET_ATT_CERTS_CMD_PAYLOAD));
TNVL_GET_ATT_CERTS_RSP_PAYLOAD *pRspPayload = nvswitch_os_malloc(sizeof(TNVL_GET_ATT_CERTS_RSP_PAYLOAD));
NVSWITCH_TIMEOUT timeout;
if (pCmdPayload == NULL || pRspPayload == NULL)
{
NVSWITCH_PRINT(device, ERROR,
"%s: Failed to allocate memory\n",
__FUNCTION__);
status = -NVL_NO_MEM;
goto ErrorExit;
}
pCmdPayload->subMessageId = TNVL_GET_ATT_CERTS_SUBMESSAGE_ID;
pCmdPayload->minorVersion = 0;
pCmdPayload->majorVersion = 1;
nvswitch_timeout_create(5 * NVSWITCH_INTERVAL_1SEC_IN_NS, &timeout);
status = nvswitch_fsp_send_and_read_message(device,
(NvU8*) pCmdPayload, sizeof(TNVL_GET_ATT_CERTS_CMD_PAYLOAD), NVDM_TYPE_TNVL,
(NvU8*) pRspPayload, sizeof(TNVL_GET_ATT_CERTS_RSP_PAYLOAD), &timeout);
if (status != NVL_SUCCESS)
{
NVSWITCH_PRINT(device, ERROR,
"%s: RPC failed for FSP cert query\n",
__FUNCTION__);
status = -NVL_ERR_INVALID_STATE;
goto ErrorExit;
}
// Validate response
if (pRspPayload->subMessageId != TNVL_GET_ATT_CERTS_SUBMESSAGE_ID)
{
NVSWITCH_PRINT(device, ERROR,
"%s: Unknown submessage Id %d, Expected %d\n",
__FUNCTION__,
pRspPayload->subMessageId, TNVL_GET_ATT_CERTS_SUBMESSAGE_ID);
status = -NVL_ERR_INVALID_STATE;
goto ErrorExit;
}
nvswitch_os_memcpy(pCertChain, pRspPayload->certChain, pRspPayload->certChainLength);
*pCertChainLength = pRspPayload->certChainLength;
ErrorExit:
nvswitch_os_free(pCmdPayload);
nvswitch_os_free(pRspPayload);
return status;
}
/*!
* This function retrieves nvswitch certificates.
*
* @param device nvswitch device pointer
* @param params certificate params
*
* @return Returns NVL_SUCCESS on success. Anything else should be considered a failure.
*/
NvlStatus
nvswitch_tnvl_get_attestation_certificate_chain_ls10
(
nvswitch_device *device,
NVSWITCH_GET_ATTESTATION_CERTIFICATE_CHAIN_PARAMS *params
)
{
NvlStatus status = NVL_SUCCESS;
NvU8 *pIkCertificate = NULL;
NvU32 ikCertificateSize = 0;
NvU8 *pAkCertificate = NULL;
NvU32 akCertificateSize = 0;
NvU8 *pCertChain = NULL;
size_t certChainLength = 0;
NvU8 *pDerCertChain = NULL;
size_t derCertChainSize = 0;
NvU8 *pCertChainBufferEnd = NULL;
NvU8 *pAttestationCertChain = NULL;
size_t attestationCertChainSize = 0;
NvU32 totalSize = 0;
if (params == NULL)
{
NVSWITCH_PRINT(device, ERROR,
"%s: Bad args!\n",
__FUNCTION__);
return -NVL_BAD_ARGS;
}
if (!nvswitch_is_tnvl_mode_enabled(device))
{
NVSWITCH_PRINT(device, ERROR,
"%s: TNVL is not enabled\n",
__FUNCTION__);
return -NVL_ERR_NOT_SUPPORTED;
}
// Allocate buffer for certificates.
certChainLength = TNVL_MAX_CERT_CHAIN_SIZE;
pCertChain = nvswitch_os_malloc(certChainLength);
derCertChainSize = TNVL_MAX_ENCODED_CERT_CHAIN_SIZE;
pDerCertChain = nvswitch_os_malloc(derCertChainSize);
attestationCertChainSize = TNVL_MAX_ENCODED_CERT_CHAIN_SIZE;
pAttestationCertChain = nvswitch_os_malloc(attestationCertChainSize);
if (pCertChain == NULL || pDerCertChain == NULL || pAttestationCertChain == NULL)
{
NVSWITCH_PRINT(device, ERROR,
"%s: Failed to allocate memory\n",
__FUNCTION__);
status = -NVL_NO_MEM;
goto ErrorExit;
}
nvswitch_os_memset(pCertChain, 0, certChainLength);
nvswitch_os_memset(pDerCertChain, 0, derCertChainSize);
nvswitch_os_memset(pAttestationCertChain, 0, attestationCertChainSize);
// Fetch Attestation cert chain from FSP
status = _nvswitch_tnvl_get_cert_chain_from_fsp_ls10(device, pCertChain, &certChainLength);
if (status != NVL_SUCCESS)
{
NVSWITCH_PRINT(device, ERROR,
"%s: Failed to get nvswitch certs from FSP\n",
__FUNCTION__);
goto ErrorExit;
}
certChainLength = certChainLength -
NVSWITCH_IK_HASH_LENGTH -
NVSWITCH_ATT_CERT_SIZE_FIELD_LENGTH -
NVSWITCH_ATT_RSVD1_FIELD_LENGTH;
//
// pCertChainBufferEnd represents last valid byte for cert buffer.
//
pCertChainBufferEnd = pCertChain + certChainLength - 1;
pIkCertificate = (NvU8 *)pCertChain;
// Calculate the size of the IK cert, and skip past it to get the AK cert.
status = _calc_x509_cert_size_ls10(device, pIkCertificate, pCertChainBufferEnd, &ikCertificateSize);
if (status != NVL_SUCCESS)
{
NVSWITCH_PRINT(device, ERROR,
"%s: Failed to calculate IK size\n",
__FUNCTION__);
goto ErrorExit;
}
pAkCertificate = (NvU8 *)pIkCertificate + ikCertificateSize;
// Calculate the size of the AK certificate.
status = _calc_x509_cert_size_ls10(device, pAkCertificate, pCertChainBufferEnd, &akCertificateSize);
if (status != NVL_SUCCESS)
{
NVSWITCH_PRINT(device, ERROR,
"%s: Failed to calculate AK size\n",
__FUNCTION__);
goto ErrorExit;
}
// Make sure we have calculated the size correctly.
if ((pAkCertificate + akCertificateSize - 1) != pCertChainBufferEnd)
{
NVSWITCH_PRINT(device, ERROR,
"%s: Error in calculating AK size\n",
__FUNCTION__);
status = -NVL_ERR_INVALID_STATE;
goto ErrorExit;
}
// Retrieve the entire certificate chain in DER format in order to validate it.
status = _tnvl_build_cert_chain_der_ls10(device,
pAkCertificate, akCertificateSize,
pIkCertificate, ikCertificateSize,
pDerCertChain,
&derCertChainSize);
if (status != NVL_SUCCESS)
{
goto ErrorExit;
}
totalSize = sizeof(TNVL_L1_CERTIFICATE_DER) +
sizeof(TNVL_L2_CERTIFICATE_DER) +
sizeof(TNVL_L3_CERTIFICATE_DER) +
akCertificateSize +
ikCertificateSize;
if (derCertChainSize != totalSize)
{
NVSWITCH_PRINT(device, ERROR,
"%s: derCertChainSize(%llu) != totalSize(0x%x) !! \n",
__FUNCTION__, ((NvU64)derCertChainSize), totalSize);
status = -NVL_ERR_INVALID_STATE;
goto ErrorExit;
}
//
// Now that the cert chain is valid, retrieve the cert chain in PEM format,
// as the Verifier can only parse PEM format.
//
status = _tnvl_build_cert_chain_pem_ls10(device,
pAkCertificate, akCertificateSize,
pIkCertificate, ikCertificateSize,
pAttestationCertChain,
&attestationCertChainSize);
if (status != NVL_SUCCESS)
{
NVSWITCH_PRINT(device, ERROR,
"%s: Failed to build PEM cert chain\n",
__FUNCTION__);
goto ErrorExit;
}
nvswitch_os_memcpy(params->attestationCertChain, pAttestationCertChain, attestationCertChainSize);
params->attestationCertChainSize = attestationCertChainSize;
ErrorExit:
nvswitch_os_free(pCertChain);
nvswitch_os_free(pDerCertChain);
nvswitch_os_free(pAttestationCertChain);
return status;
}
NvlStatus
nvswitch_tnvl_get_attestation_report_ls10
(
nvswitch_device *device,
NVSWITCH_GET_ATTESTATION_REPORT_PARAMS *params
)
{
NvlStatus status;
TNVL_GET_ATT_REPORT_CMD_PAYLOAD *pCmdPayload;
TNVL_GET_ATT_REPORT_RSP_PAYLOAD *pRspPayload;
NVSWITCH_TIMEOUT timeout;
if (!nvswitch_is_tnvl_mode_enabled(device))
{
NVSWITCH_PRINT(device, ERROR,
"%s: TNVL is not enabled\n",
__FUNCTION__);
return -NVL_ERR_NOT_SUPPORTED;
}
pCmdPayload = nvswitch_os_malloc(sizeof(TNVL_GET_ATT_REPORT_CMD_PAYLOAD));
pRspPayload = nvswitch_os_malloc(sizeof(TNVL_GET_ATT_REPORT_RSP_PAYLOAD));
if (pCmdPayload == NULL || pRspPayload == NULL)
{
NVSWITCH_PRINT(device, ERROR,
"%s: Failed to allocate memory\n",
__FUNCTION__);
status = -NVL_NO_MEM;
goto ErrorExit;
}
// Request the Attestation Report using the provided nonce, signed by the AK cert.
pCmdPayload->subMessageId = TNVL_GET_ATT_REPORT_SUBMESSAGE_ID;
pCmdPayload->minorVersion = 0;
pCmdPayload->majorVersion = 1;
nvswitch_os_memcpy(pCmdPayload->nonce, params->nonce, NVSWITCH_NONCE_SIZE);
nvswitch_timeout_create(10 * NVSWITCH_INTERVAL_1SEC_IN_NS, &timeout);
status = nvswitch_fsp_send_and_read_message(device,
(NvU8*) pCmdPayload, sizeof(TNVL_GET_ATT_REPORT_CMD_PAYLOAD), NVDM_TYPE_TNVL,
(NvU8*) pRspPayload, sizeof(TNVL_GET_ATT_REPORT_RSP_PAYLOAD), &timeout);
if (status != NVL_SUCCESS)
{
NVSWITCH_PRINT(device, ERROR,
"%s: Failed to get nvswitch measurements from FSP\n",
__FUNCTION__);
goto ErrorExit;
}
// Validate response
if (pRspPayload->subMessageId != TNVL_GET_ATT_REPORT_SUBMESSAGE_ID)
{
NVSWITCH_PRINT(device, ERROR,
"%s: Unknown submessage Id %d, Expected %d\n",
__FUNCTION__,
pRspPayload->subMessageId, TNVL_GET_ATT_REPORT_SUBMESSAGE_ID);
status = -NVL_ERR_INVALID_STATE;
goto ErrorExit;
}
nvswitch_os_memcpy(params->attestationReport,
pRspPayload->measurementBuffer, pRspPayload->measurementSize);
params->attestationReportSize = pRspPayload->measurementSize;
ErrorExit:
nvswitch_os_free(pCmdPayload);
nvswitch_os_free(pRspPayload);
return status;
}
NvlStatus
nvswitch_detect_tnvl_mode_ls10
(
nvswitch_device *device
)
{
NvU32 val;
// Detect for TNVL mode
val = NVSWITCH_SAW_RD32_LS10(device, _NVLSAW, _TNVL_MODE);
if (FLD_TEST_DRF(_NVLSAW, _TNVL_MODE, _STATUS, _ENABLED, val))
{
NVSWITCH_PRINT(device, ERROR,
"%s: TNVL Mode Detected\n",
__FUNCTION__);
device->tnvl_mode = NVSWITCH_DEVICE_TNVL_MODE_ENABLED;
}
return NVL_SUCCESS;
}
NvBool
nvswitch_is_tnvl_mode_enabled_ls10
(
nvswitch_device *device
)
{
return (device->tnvl_mode != NVSWITCH_DEVICE_TNVL_MODE_DISABLED);
}
NvBool
nvswitch_is_tnvl_mode_locked_ls10
(
nvswitch_device *device
)
{
return (device->tnvl_mode == NVSWITCH_DEVICE_TNVL_MODE_LOCKED);
}
NvlStatus
nvswitch_tnvl_send_fsp_lock_config_ls10
(
nvswitch_device *device
)
{
NvlStatus status;
TNVL_LOCK_CONFIG_CMD_PAYLOAD *pCmdPayload;
TNVL_LOCK_CONFIG_RSP_PAYLOAD *pRspPayload;
NVSWITCH_TIMEOUT timeout;
if (!nvswitch_is_tnvl_mode_enabled(device))
{
NVSWITCH_PRINT(device, ERROR,
"%s: TNVL is not enabled\n",
__FUNCTION__);
return -NVL_ERR_NOT_SUPPORTED;
}
pCmdPayload = nvswitch_os_malloc(sizeof(TNVL_LOCK_CONFIG_CMD_PAYLOAD));
pRspPayload = nvswitch_os_malloc(sizeof(TNVL_LOCK_CONFIG_RSP_PAYLOAD));
if (pCmdPayload == NULL || pRspPayload == NULL)
{
NVSWITCH_PRINT(device, ERROR,
"%s: Failed to allocate memory\n",
__FUNCTION__);
status = -NVL_NO_MEM;
goto ErrorExit;
}
pCmdPayload->subMessageId = TNVL_LOCK_CONFIG_SUBMESSAGE_ID;
pCmdPayload->minorVersion = 0;
pCmdPayload->majorVersion = 1;
nvswitch_timeout_create(5 * NVSWITCH_INTERVAL_1SEC_IN_NS, &timeout);
status = nvswitch_fsp_send_and_read_message(device,
(NvU8*) pCmdPayload, sizeof(TNVL_LOCK_CONFIG_CMD_PAYLOAD), NVDM_TYPE_TNVL,
(NvU8*) pRspPayload, sizeof(TNVL_LOCK_CONFIG_RSP_PAYLOAD), &timeout);
if (status != NVL_SUCCESS)
{
NVSWITCH_PRINT(device, ERROR,
"%s: RPC failed for FSP lock config command\n",
__FUNCTION__);
status = -NVL_ERR_INVALID_STATE;
goto ErrorExit;
}
// Validate response
if (pRspPayload->subMessageId != TNVL_LOCK_CONFIG_SUBMESSAGE_ID)
{
NVSWITCH_PRINT(device, ERROR,
"%s: Unknown submessage Id %d, Expected %d\n",
__FUNCTION__,
pRspPayload->subMessageId, TNVL_LOCK_CONFIG_SUBMESSAGE_ID);
status = -NVL_ERR_INVALID_STATE;
goto ErrorExit;
}
ErrorExit:
nvswitch_os_free(pCmdPayload);
nvswitch_os_free(pRspPayload);
return status;
}
NvlStatus
nvswitch_tnvl_get_status_ls10
(
nvswitch_device *device,
NVSWITCH_GET_TNVL_STATUS_PARAMS *params
)
{
params->status = device->tnvl_mode;
return NVL_SUCCESS;
}
static NvBool
_nvswitch_tnvl_eng_wr_cpu_allow_list_ls10
(
nvswitch_device *device,
NVSWITCH_ENGINE_ID eng_id,
NvU32 offset
)
{
switch (eng_id)
{
case NVSWITCH_ENGINE_ID_SOE:
case NVSWITCH_ENGINE_ID_GIN:
case NVSWITCH_ENGINE_ID_FSP:
return NV_TRUE;
case NVSWITCH_ENGINE_ID_SAW:
{
if (offset == NV_NVLSAW_DRIVER_ATTACH_DETACH)
return NV_TRUE;
break;
}
case NVSWITCH_ENGINE_ID_NPG:
{
if ((offset == NV_NPG_INTR_RETRIGGER(0)) ||
(offset == NV_NPG_INTR_RETRIGGER(1)))
return NV_TRUE;
break;
}
case NVSWITCH_ENGINE_ID_CPR:
{
if ((offset == NV_CPR_SYS_INTR_RETRIGGER(0)) ||
(offset == NV_CPR_SYS_INTR_RETRIGGER(1)))
return NV_TRUE;
break;
}
case NVSWITCH_ENGINE_ID_MINION:
{
if ((offset == NV_MINION_NVLINK_DL_STAT(0)) ||
(offset == NV_MINION_NVLINK_DL_STAT(1)) ||
(offset == NV_MINION_NVLINK_DL_STAT(2)) ||
(offset == NV_MINION_NVLINK_DL_STAT(3)))
return NV_TRUE;
break;
}
default :
return NV_FALSE;
}
return NV_FALSE;
}
void
nvswitch_tnvl_eng_wr_32_ls10
(
nvswitch_device *device,
NVSWITCH_ENGINE_ID eng_id,
NvU32 eng_bcast,
NvU32 eng_instance,
NvU32 base_addr,
NvU32 offset,
NvU32 data
)
{
if (device->nvlink_device->pciInfo.bars[0].pBar == NULL)
{
NVSWITCH_PRINT(device, ERROR,
"%s: register write failed at offset 0x%x\n",
__FUNCTION__, offset);
return;
}
if (!nvswitch_is_tnvl_mode_enabled(device))
{
NVSWITCH_PRINT_SXID(device, NVSWITCH_ERR_HW_HOST_TNVL_ERROR,
"ENG reg-write failed. TNVL mode is not enabled\n");
return;
}
if (_nvswitch_tnvl_eng_wr_cpu_allow_list_ls10(device, eng_id, offset))
{
nvswitch_os_mem_write32((NvU8 *)device->nvlink_device->pciInfo.bars[0].pBar + base_addr + offset, data);
return;
}
if (nvswitch_is_tnvl_mode_locked(device))
{
NVSWITCH_PRINT_SXID(device, NVSWITCH_ERR_HW_HOST_TNVL_ERROR,
"TNVL ENG_WR failure - 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n",
eng_id, eng_instance, eng_bcast, base_addr, offset, data);
NVSWITCH_PRINT_SXID(device, NVSWITCH_ERR_HW_HOST_TNVL_ERROR,
"TNVL mode is locked\n");
return;
}
if (nvswitch_soe_eng_wr_32_ls10(device, eng_id, eng_bcast, eng_instance, base_addr, offset, data) != NVL_SUCCESS)
{
NVSWITCH_PRINT_SXID(device, NVSWITCH_ERR_HW_HOST_TNVL_ERROR,
"TNVL ENG_WR failure - 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n",
eng_id, eng_instance, eng_bcast, base_addr, offset, data);
NVSWITCH_PRINT(device, ERROR,
"%s: SOE ENG_WR failed for 0x%x[%d] %s @0x%08x+0x%06x = 0x%08x\n",
__FUNCTION__,
eng_id, eng_instance,
(
(eng_bcast == NVSWITCH_GET_ENG_DESC_TYPE_UNICAST) ? "UC" :
(eng_bcast == NVSWITCH_GET_ENG_DESC_TYPE_BCAST) ? "BC" :
(eng_bcast == NVSWITCH_GET_ENG_DESC_TYPE_MULTICAST) ? "MC" :
"??"
),
base_addr, offset, data);
}
}
static NvBool
_nvswitch_tnvl_reg_wr_cpu_allow_list_ls10
(
nvswitch_device *device,
NvU32 offset
)
{
if ((offset >= DRF_BASE(NV_PFSP)) &&
(offset <= DRF_EXTENT(NV_PFSP)))
{
return NV_TRUE;
}
if ((offset >= NV_PTOP_UNICAST_SW_DEVICE_BASE_SOE_0 + DRF_BASE(NV_SOE)) &&
(offset <= NV_PTOP_UNICAST_SW_DEVICE_BASE_SOE_0 + DRF_EXTENT(NV_SOE)))
{
return NV_TRUE;
}
return NV_FALSE;
}
void
nvswitch_tnvl_reg_wr_32_ls10
(
nvswitch_device *device,
NvU32 offset,
NvU32 data
)
{
if (device->nvlink_device->pciInfo.bars[0].pBar == NULL)
{
NVSWITCH_PRINT(device, ERROR,
"%s: register write failed at offset 0x%x\n",
__FUNCTION__, offset);
NVSWITCH_ASSERT(0);
return;
}
if (!nvswitch_is_tnvl_mode_enabled(device))
{
NVSWITCH_PRINT_SXID(device, NVSWITCH_ERR_HW_HOST_TNVL_ERROR,
"Reg-write failed. TNVL mode is not enabled\n");
return;
}
if (_nvswitch_tnvl_reg_wr_cpu_allow_list_ls10(device, offset))
{
nvswitch_os_mem_write32((NvU8 *)device->nvlink_device->pciInfo.bars[0].pBar + offset, data);
return;
}
if (nvswitch_is_tnvl_mode_locked(device))
{
NVSWITCH_PRINT_SXID(device, NVSWITCH_ERR_HW_HOST_TNVL_ERROR,
"TNVL REG_WR failure - 0x%08x, 0x%08x\n", offset, data);
NVSWITCH_PRINT_SXID(device, NVSWITCH_ERR_HW_HOST_TNVL_ERROR,
"TNVL mode is locked\n");
return;
}
if (nvswitch_soe_reg_wr_32_ls10(device, offset, data) != NVL_SUCCESS)
{
NVSWITCH_PRINT_SXID(device, NVSWITCH_ERR_HW_HOST_TNVL_ERROR,
"TNVL REG_WR failure - 0x%08x, 0x%08x\n", offset, data);
}
}
void
nvswitch_tnvl_disable_interrupts_ls10
(
nvswitch_device *device
)
{
//
// In TNVL locked disable non-fatal NVLW, NPG, and legacy interrupt,
// disable additional non-fatals on those partitions.
//
NVSWITCH_ENG_WR32(device, GIN, , 0, _CTRL, _CPU_INTR_LEAF_EN_CLEAR(NV_CTRL_CPU_INTR_NVLW_NON_FATAL_IDX),
0xFFFF);
NVSWITCH_ENG_WR32(device, GIN, , 0, _CTRL, _CPU_INTR_LEAF_EN_CLEAR(NV_CTRL_CPU_INTR_NPG_NON_FATAL_IDX),
0xFFFF);
NVSWITCH_ENG_WR32(device, GIN, , 0, _CTRL, _CPU_INTR_LEAF_EN_CLEAR(NV_CTRL_CPU_INTR_UNITS_IDX),
0xFFFFFFFF);
}