第 4 章 - Azure RTO NetX Secure 服务的说明

本章按字母顺序介绍了所有 Azure RTOS NetX Secure 服务(如下所列)。

在以下 API 说明的“返回值”部分中,以粗体显示的值不受定义用于禁用 API 错误检查的 NX_SECURE_DISABLE_ERROR_CHECKING 宏影响,而不以粗体显示的值则完全禁用。

nx_secure_crypto_table_self_test

根据加密方法执行自检

原型

UINT nx_secure_crypto_table_self_test(
                                  const NX_SECURE_TLS_CRYPTO *crypto_table,
                                  VOID *metadata, UINT metadata_size);

说明

此服务通过运行加密方法自检来进行验证。 只有在生成 NetX Secure 库时定义了 NX_SECURE_POWER_ON_SELF_TEST_MODULE_INTEGRITY_CHECK 符号,才能使用自检。

对于每个受支持的加密方法,自检程序都提供预定义的输入数据,并验证输出是否与预定义的预期值一致。

NetX Secure 加密自检支持以下算法和密钥大小:

  • DES:加密和解密
  • 三重 DES (3DES):加密和解密
  • AES:在 CBC 模式和计数器模式下,128、192、256 位密钥大小,加密和解密。
  • HMAC-MD5:身份验证和哈希计算
  • HMAC-SHA:SHA1-96,SHA1-160,SHA2-256,SHA2-384,SHA2- 512,身份验证和哈希计算
  • MD5:身份验证
  • 伪随机函数 (PRF):PRF_HMAC_SHA1 和 PRF_HMAC_SHA2-256
  • RSA:1024、2048、4096 位 RSA 幂模运算
  • SHA:SHA1(96 和 160 位)、SHA2(256 位、384 位、512 位)身份验证

此函数具有适用于上面列出的加密算法的内置矢量。 但它只测试传入此函数的 cipher_table 中列出的算法。 例如,对于仅使用密码套件 TLS_RSA_WITH_AES_128_CBC_SHA 的 TLS 会话,此函数将对 RSA(1024、2048、4096 位)、AES-CBC(128 位)和 SHA1 执行自检。

参数

  • crypto_table:指向 TLS 会话正在使用的加密表的指针。 这个 crypto_table 将会传递到 nx_secure_tls_session_create() 调用中。
  • metadata:指向用于加密元数据区域所在空间的指针。 .
  • metadata_size:元数据缓冲区的大小。

返回值

  • NX_SECURE_TLS_SUCCESS (0X00):成功测试了提供的加密方法。
  • NX_PTR_ERROR (0x07):加密方法结构无效
  • NX_NOT_SUCCESSFUL (0X43):加密自检失败。

允许来自

初始化、线程

示例

/* crypto_tls_ciphers is the cipher table for the TLS session. */
/* metadata_buffer is the memory area used by the cipher functions. */

/* The following function verifies the supplied ciphersuties using the built-in
   self test. */

if (nx_secure_crypto_table_self_test(&crypto_tls_ciphers, metadata_buffer,
    sizeof(metadata_buffer)))
{
    printf("Crypto self test failed!\r\n");
    exit(0);
}
else
{
    printf("Crypto self test succeed!\r\n");
}

/* Now the ciphersuites are successfully test, it can be used in
   nx_secure_tls_session_create() */

另请参阅

  • nx_secure_tls_session_create

nx_secure_module_hash_compute

使用用户提供的哈希函数计算哈希值

原型

UINT nx_secure_module_hash_compute(
                      NX_CRYPTO_METHOD *hamc_ptr,
                      UINT start_address, UINT end_address,
                      UCHAR *key, UINT key_length,
                      VOID *metadata, UINT metadata_size,
                      UCHAR *output_buffer, UINT output_buffer_size,
                      UINT *actual_size);

说明

此函数使用提供的 HMAC 加密方法和密钥字符串,计算指定内存区域内数据流的哈希值。 仅当 NetX Secure 库是在定义以下符号的情况下生成时,才能使用模块哈希计算函数:NX_SECURE_POWER_ON_SELF_TEST_MODULE_INTEGRITY_CHECK

参数

  • hmac_ptr:指向用于计算哈希值的 HMAC 加密方法的指针。
  • start_address:数据缓冲区的起始地址
  • end_address:数据缓冲区的结束地址。 请注意,哈希计算不会涵盖此 end_address 的数据。
  • key:在 HMAC 计算中使用的密钥字符串。
  • key_length:字符串的大小(以字节为单位)。
  • metadata:指向 HMAC 算法使用的空间的指针。
  • metadata_size:元数据缓冲区的大小。
  • output_buffer:存储哈希输出的内存位置。
  • output_buffer_size:输出缓冲区的可用空间(以字节为单位)
  • actual_size:由此函数返回,表示写入 output_buffer 的实际字节数。

返回值

  • 0:已成功计算哈希值。
  • 1:哈希计算失败。

允许来自

初始化、线程

示例

/* Define the HMAC SHA256 method */
NX_CRYPTO_METHOD hmac_sha256 =
{
    NX_CRYPTO_AUTHENTICATION_HMAC_SHA2_256,    /* HMAC SHA256 algorithm  */
    0,                                         /* Key size, not used     */
    0,                                         /* IV size, not used      */
    NX_CRYPTO_HMAC_SHA256_ICV_FULL_LEN_IN_BITS,/* Transmitted ICV size   */
    NX_CRYPTO_SHA2_BLOCK_SIZE_IN_BYTES,        /* Block size in bytes    */
    sizeof(NX_CRYPTO_SHA256_HMAC),             /* Metadata size in bytes */
    _nx_crypto_method_hmac_sha256_init,        /* HMAC SHA256 init       */
    _nx_crypto_method_hmac_sha256_cleanup,     /* HMAC SHA256 cleanup    */
    _nx_crypto_method_hmac_sha256_operation    /* HMAC SHA256 operation  */
};

/* Define the hash key being used. */
const CHAR hash_key = “my hash key”;

/* Define starting address. */
UINT starting_address = 0x10000;

/* Define the ending address.
   Note that the hash computation covers the memory location
   before the ending address. */
UINT ending_address = 0x11000;

/* Declare the output buffer. */
#define OUTPUT_BUFFER_SIZE
UCHAR output_buffer[OUTPUT_BUFFER_SIZE];

UINT actual_size;

/* Declare 1K bytes of metadata buffer area. */
UCHAR metadata_buffer[1024];

/* Compute the hash value of the data between 0x10000 – 0x10FFF */
nx_secure_module_hash_compute(&hmac_sha256,
                              starting_address, ending_address,
                              hash_key, strlen(hash_key),
                              metadata_buffer, sizeof(metadata_buffer),
                              output_buffer, OUTPUT_BUFFER_SIZE, &actual_size);

/* If this function returns “0”, the hash value has been computed and is stored
   in output_buffer. */

另请参阅

  • nx_secure_crypto_method_self_test

nx_secure_tls_active_certificate_set

为 NetX Secure TLS 会话设置活动标识证书

原型

UINT  nx_secure_tls_active_certificate_set(
                   NX_SECURE_TLS_SESSION *tls_session,
                   NX_SECURE_X509_CERT *certificate);

说明

此服务应在会话回调内调用(请参阅 nx_secure_tls_session_client_callback_set 和 nx_secure_tls_session_server_callback_set)。 使用之前初始化的 NX_SECURE_X509_CERT 结构调用时,系统将使用此证书而不是默认的身份证书。 在大多数情况下,必须将此证书添加到本地存储(参阅 nx_secure_tls_local_certificate_add),否则 TLS 握手可能会失败。

此服务能够允许 TLS 支持多个身份证书。 这对服务多个网络地址的 TLS 服务器非常有用,该服务器可以根据客户端的入口点选择合适的证书提供给远程客户端。 TLS 客户端可以使用此例程在服务器通过 TLS 握手识别自己的身份后,更改运行时发送到远程服务器的证书。

如果多个证书可能共享相同的 X.509 可分辨名称,则需要使用 nx_secure_tls_server_certificate_add 添加证书,这会引入与证书分开的数字标识符。

参数

  • session_ptr:指向传递到会话回调的 TLS 会话实例的指针。
  • certificate:指向要用于当前会话的已初始化 X.509 证书的指针。

返回值

  • NX_SUCCESS (0x00):成功将证书分配给会话。
  • NX_PTR_ERROR (0X07):TLS 会话或证书指针无效。

允许来自

线程数

示例

#define TLS_SNI_SERVER_NAME “www.example.com”
#define TLS_DEFAULT_SERVER_CERT_ID 2
#define TLS_EXAMPLE_CERT_ID 3


/* Callback for ClientHello extensions processing. */
static ULONG tls_server_callback(NX_SECURE_TLS_SESSION *tls_session,
                                 NX_SECURE_TLS_HELLO_EXTENSION *extensions,
                                 UINT num_extensions)
{
NX_SECURE_X509_DNS_NAME dns_name;
INT compare_value;
UINT status;
NX_SECURE_X509_CERT *cert_ptr;

    /* Grab a pointer to our default certificate in case the SNI extension is not
       available or the specified server name is unknown. */
    nx_secure_tls_server_certificate_find(tls_session, &cert_ptr,
                                     TLS_DEFAULT_SERVER_CERT_ID);


    /* Process Server Name Indication extension. */
    status = _nx_secure_tls_session_sni_extension_parse(tls_session, extensions,
                                                    num_extensions, &dns_name);

    /* If no extension found, that is OK. Use default certificate. */
    if(status == NX_SUCCESS)
    {
          /* SNI extension found, select an active certificate based on the server
             name. */

          /* Make sure our SNI name matches. */
          compare_value = memcmp(dns_name.nx_secure_x509_dns_name,
                                TLS_SNI_SERVER_NAME, strlen(TLS_SNI_SERVER_NAME));

          if(compare_value == 0 && dns_name.nx_secure_x509_dns_name_length !=
             strlen(TLS_SNI_SERVER_NAME))
          {
             /* Found a match, find the certificate we want to use. */
             _nx_secure_tls_server_certificate_find(tls_session, &cert_ptr,
                                                      TLS_EXAMPLE_CERT_ID);
          }
          else
          {
             /* No matching server name found. The application may choose to simply
                provide the default certificate (and probably resulting in an error
                in the remote client) or returning an error here to end the
                handshake. A user-defined non-zero error code will be sufficient –
                the error code will abort the TLS handshake and be returned to the
                caller that started the server. */
                return(0x500);
          }
      }
      else
      {
      }
      /* Set the certificate we want to use. */
      nx_secure_tls_active_certificate_set(tls_session, cert_ptr);

      /* Return success to continue TLS handshake. */
      return(NX_SUCCESS);
}

/* Sockets, sessions, certificates defined in global static space to preserve
   application stack. */
NX_SECURE_TLS_SESSION server_tls_session;

/* Application where TLS session is started. */
void main()
{
    /* Create a TLS session for our socket. Ciphers and metadata defined
       elsewhere. See nx_secure_tls_session_create reference for more
       information. */
    status =  nx_secure_tls_session_create(&server_tls_session,
                                           &nx_crypto_tls_ciphers,
                                           server_crypto_metadata,
                                           sizeof(server_crypto_metadata));

    /* Check for error.  */
    if(status)
    {
        printf("Error in function nx_secure_tls_session_create: 0x%x\n", status);
    }

    /* Setup our packet reassembly buffer. See
       nx_secure_tls_session_packet_buffer_set for more information. */
    nx_secure_tls_session_packet_buffer_set(&server_tls_session,
                                      server_packet_buffer,
                                      sizeof(server_packet_buffer));


    /* Set callback for server TLS extension handling. */
    _nx_secure_tls_session_server_callback_set(&server_tls_session,
                                              tls_server_callback);

    /* Initialize our certificates – certificate data defined elsewhere. See
       section “Importing X.509 Certificates into NetX Secure” for more
       information. */
    nx_secure_x509_certificate_initialize(&default_certificate,
                                      default_cert_der,
                                      default _cert_der_len, NX_NULL, 0,
                                      default_cert_key_der,
                                      default_cert_key_der_len,
                                      NX_SECURE_X509_KEY_TYPE_RSA_PKCS1_DER);

    /* Add the certificate to the local store using a numeric ID. */
    nx_secure_tls_server_certificate_add(&server_tls_session,
                                         &default_certificate,
                                         TLS_DEFAULT_SERVER_CERT_ID);

    /* Alternative identity certificate, needs to have a private key! */
    nx_secure_x509_certificate_initialize(&example_certificate,
                                      example_cert_der,
                                      example cert_der_len, NX_NULL, 0,
                                      example_cert_key_der,
                                      example_cert_key_der_len,
                                      NX_SECURE_X509_KEY_TYPE_RSA_PKCS1_DER);

    /* Add the certificate to the local store using a numeric ID. */
    nx_secure_tls_server_certificate_add(&server_tls_session,
                                         &example_certificate,
                                         TLS_EXAMPLE_CERT_ID);

    /* Now we can start the TLS session as normal. */
       …
}

另请参阅

  • nx_secure_x509_certificate_initialize
  • nx_secure_tls_local_certificate_add
  • nx_secure_tls_session_client_callback_set
  • nx_secure_tls_session_server_callback_set
  • nx_secure_tls_server_certificate_add
  • nx_secure_tls_server_certificate_find
  • nx_secure_tls_server_certificate_remove

nx_secure_tls_client_psk_set

为 NetX Secure TLS 客户端会话设置预共享密钥

原型

UINT  nx_secure_tls_client_psk_set(NX_SECURE_TLS_SESSION *session_ptr,
                              UCHAR *pre_shared_key, UINT psk_length,
                              UCHAR *psk_identity, UINT identity_length,
                              UCHAR *hint, UINT hint_length);

说明

此服务向 TLS 会话控制块添加预共享密钥 (PSK)、其标识字符串和标识提示,并将该 PSK 设置为在后续的 TLS 客户端连接中使用。 如果启用并使用 PSK 密码套件,则会用 PSK 来代替数字证书。

在这种情况下,PSK 与 TLS 客户端要与之通信的特定远程 TLS 服务器相关联。 通过此 API 设置的 PSK 将在下一次 TLS 握手期间提供给远程 TLS 服务器主机。

参数

  • session_ptr:指向之前创建的 TLS 会话实例的指针。
  • pre_shared_key:实际的 PSK 值。
  • psk_length:PSK 值的长度。
  • psk_identity:用于标识此 PSK 值的字符串。
  • identity_length:PSK 标识的长度。
  • hint:用于表示要从 TLS 服务器上选择的 PSK 组的字符串。
  • hint_length:提示字符串的长度。

返回值

  • NX_SUCCESS (0X00):成功添加 PSK。
  • NX_PTR_ERROR (0X07):TLS 会话指针无效。
  • NX_SECURE_TLS_NO_MORE_PSK_SPACE (0X125):不能再添加一个 PSK。

允许来自

线程数

示例

/* PSK value.  */
UCHAR psk[] = { 0x1a, 0x2b, 0x3c, 0x4d };

/* Add PSK to TLS session.  */
status =  nx_secure_tls_client_psk_set(&tls_session, psk, sizeof(psk), “psk_1”, 4,
“Client_identity”, 15);


/* If status is NX_SUCCESS the PSK was successfully added.  */

另请参阅

  • nx_secure_tls_psk_add
  • nx_secure_x509_certificate_initialize
  • nx_secure_tls_session_create
  • nx_secure_tls_remote_certificate_allocate
  • nx_secure_tls_local_certificate_add

nx_secure_tls_initialize

初始化 NetX Secure TLS 模块

原型

VOID nx_secure_tls_initialize(VOID);

说明

此服务用于初始化 NetX Secure TLS 模块。 必须先调用此服务,才能访问其他 NetX Secure 服务。

参数

返回值

允许来自

初始化、线程

示例

/* Initializes the TLS module. */
Nx_secure_tls_initialize();

另请参阅

  • nx_secure_tls_session_create

nx_secure_tls_local_certificate_add

向 NetX Secure TLS 会话添加本地证书

原型

UINT  nx_secure_tls_local_certificate_add(
              NX_SECURE_TLS_SESSION *session_ptr,
              NX_SECURE_X509_CERT *certificate_ptr);

说明

此服务将初始化的 NX_SECURE_X509_CERT 结构实例添加到 TLS 会话的本地存储中。 如果此证书在使用 nx_secure_x509_certificate_initialize 初始化证书结构期间已标记为标识证书,TLS 堆栈则可将其用于在 TLS 握手期间识别设备,或作为颁发者,这是 TLS 握手期间提供给远程主机的证书链的一部分。

如果需要多个具有相同公用名的本地证书,可以使用 nx_secure_tls_server_certificate_add 服务添加证书(请参阅下面的警告)。

证书是 TLS 服务器模式的“必需”项。

证书是 TLS 客户端模式的“可选”项。

重要

使用 nx_secure_tls_server_certificate_add 时,不应将此 API 用于同一个 TLS 会话。 服务器证书 API 对每个证书使用唯一的数字标识符,而 nx_secure_tls_local_certificate_add 基于 X.509 公用名编制索引。 对于使用单个标识证书的应用程序,本地证书服务提供了替代数字标识符的便捷方法,即使用公用名,这样应用程序就无需跟踪数字标识符。

参数

  • session_ptr:指向之前创建的 TLS 会话实例的指针。
  • certificate_ptr:指向已初始化的 TLS 证书实例的指针。

返回值

  • NX_SUCCESS (0X00):成功添加证书。
  • NX_INVALID_PARAMETERS (0X4D):尝试添加的证书无效或重复。
  • NX_PTR_ERROR (0X07):TLS 会话或证书指针无效。

允许来自

线程数

示例

/* Initialize certificate structure. */
status =  nx_secure_x509_certificate_initialize(&certificate, certificate_data,
500, private_key, 64);

/* Add certificate to TLS session.  */
status =  nx_secure_tls_local_certificate_add(&tls_session, &certificate);


/* If status is NX_SUCCESS the certificate was successfully added.  */

另请参阅

  • nx_secure_x509_certificate_initialize
  • nx_secure_tls_session_create
  • nx_secure_tls_remote_certificate_allocate
  • nx_secure_tls_local_certificate_remove
  • nx_secure_tls_local_certificate_find

nx_secure_tls_local_certificate_find

按公用名在 NetX Secure TLS 会话中查找本地证书

原型

UINT  nx_secure_tls_local_certificate_find(NX_SECURE_TLS_SESSION
                        *session_ptr, NX_SECURE_X509_CERT
                        **certificate, UCHAR *common_name, UINT
                        name_length);

说明

此服务在 TLS 会话的本地设备证书存储中查找证书,并返回指向存储区中 NX_SECURE_X509_CERT 结构的指针。 common_name 参数及其长度 (name_length) 用于识别存储区中的证书,方法是匹配证书的 X.509 使用者公用名字段。

如果存在多个具有相同公用名的证书,则只返回第一个证书,可改用 nx_secure_tls_server_certificate_find。

重要

使用 nx_secure_tls_server_certificate_add 时,不应将此 API 用于同一个 TLS 会话。 服务器证书 API 对每个证书使用唯一的数字标识符,而 nx_secure_tls_local_certificate_add 基于 X.509 公用名编制索引。 对于使用单个标识证书的应用程序,本地证书服务提供了替代数字标识符的便捷方法,即使用公用名,这样应用程序就无需跟踪数字标识符。

参数

  • session_ptr:指向之前创建的 TLS 会话实例的指针。
  • certificate:返回指向匹配证书的指针。
  • common_name:要匹配(DNS 名称)的公用名字符串。
  • name_length:common_name 字符串数据的长度。

返回值

  • NX_SUCCESS (0x00):已找到证书,并在“certificate”参数中返回了指针。
  • NX_SECURE_TLS_CERTIFICATE_NOT_FOUND (0x119):找不到具有提供的公用名的证书。
  • NX_PTR_ERROR (0X07):TLS 会话、证书指针或公用名字符串无效。

允许来自

线程数

示例

NX_SECURE_X509_CERT *certificate_ptr;

/* Initialize certificate structure. */
status =  nx_secure_x509_certificate_initialize(&certificate, certificate_data,
500, private_key, 64);

/* Add certificate to TLS session.  */
status =  nx_secure_tls_local_certificate_add(&tls_session, &certificate);


/* If status is NX_SUCCESS the certificate was successfully added.  */

status = nx_secure_tls_local_certificate_find(&tls_session, &certificate_ptr,
                                      “common name”, strlen(“common name”));

/* If status is NX_SUCCESS the variable “certificate_ptr” points to a certificate
   structure containing a certificate with the Common Name “common name”. */

另请参阅

  • nx_secure_x509_certificate_initialize
  • nx_secure_tls_session_create
  • nx_secure_tls_remote_certificate_allocate
  • nx_secure_tls_local_certificate_remove
  • nx_secure_tls_local_certificate_add

nx_secure_tls_local_certificate_remove

从 NetX Secure TLS 会话中删除本地证书

原型

UINT  nx_secure_tls_local_certificate_remove(NX_SECURE_TLS_SESSION
                  *session_ptr, UCHAR *common_name, UINT
                  common_name_length);

说明

此服务从 TLS 会话中删除本地证书实例,并将其键入证书中的“Common Name”字段。

重要

使用 nx_secure_tls_server_certificate_add 时,不应将此 API 用于同一个 TLS 会话。 服务器证书 API 对每个证书使用唯一的数字标识符,而 nx_secure_tls_local_certificate_add 基于 X.509 公用名编制索引。 对于使用单个标识证书的应用程序,本地证书服务提供了替代数字标识符的便捷方法,即使用公用名,这样应用程序就无需跟踪数字标识符。

参数

  • session_ptr:指向之前创建的 TLS 会话实例的指针。
  • common_name:要删除的证书的公用名值。
  • common_name_length:公用名字符串的长度。

返回值

  • NX_SUCCESS (0X00):成功添加证书。
  • NX_PTR_ERROR (0X07):TLS 会话指针无效。
  • NX_SECURE_TLS_CERTIFICATE_NOT_FOUND (0X119):找不到证书。

允许来自

线程数

示例

/* Add certificate to TLS session.  */
status =  nx_secure_tls_local_certificate_remove(&tls_session,
                                                “www.example.com”, 15);


/* If status is NX_SUCCESS the certificate was successfully removed.  */

另请参阅

  • nx_secure_x509_certificate_initialize
  • nx_secure_tls_session_create
  • nx_secure_tls_remote_certificate_allocate
  • nx_secure_tls_local_certificate_add

nx_secure_tls_metadata_size_calculate

计算 NetX Secure TLS 会话的加密元数据的大小

原型

UINT  nx_secure_tls_metadata_size_calculate(
                        const NX_SECURE_TLS_CRYPTO *crypto_table,
                        ULONG *metadata_size);

说明

此服务计算并返回特定 TLS 会话和 TLS 加密表所需的加密元数据的大小。请参阅“使用加密方法初始化 TLS”一节,了解有关加密密码表的详细信息。

此服务应使用所需的加密表进行调用,以便计算传递到 nx_secure_tls_session_create 中的元数据缓冲区的大小。

参数

  • crypto_table:指向完整的 NetX Secure TLS 加密表的指针。
  • metadata_size:计算大小的输出(以字节为单位)。

返回值

  • NX_SUCCESS (0X00):成功计算元数据大小。
  • NX_PTR_ERROR (0x07):加密表或返回大小指针无效。

允许来自

线程数

示例

/* Pointer to the platform-specific cipher table. */
extern nx_crypto_tls_ciphers;

/* Return variable for metadata size. */
ULONG crypto_metadata_size;

/* Calculate metadata size.  */
status =  nx_secure_tls_metadata_size_calculate(&nx_crypto_tls_ciphers,
                                                &crypto_metadata_size);


/* If status is NX_SUCCESS then crypto_metadata_size contains the size of the
   metadata buffer for the table nx_crypto_tls_ciphers.  */

另请参阅

  • nx_secure_tls_session_create

nx_secure_tls_packet_allocate

为 NetX Secure TLS 会话分配数据包

原型

UINT  nx_secure_tls_packet_allocate(NX_SECURE_TLS_SESSION *session_ptr,
                                    NX_PACKET_POOL *pool_ptr,
                                    NX_PACKET **packet_ptr,
                                    ULONG wait_option);

说明

此服务从指定的 NX_PACKET_POOL 为指定的活动 TLS 会话分配 NX_PACKET。 此服务应由应用程序调用,以便分配要通过 TLS 连接发送的数据包。 必须先初始化 TLS 会话,然后才能调用此服务。

系统已正确初始化分配的数据包,因此可在填充数据包数据后添加 TLS 标头和脚注数据。 否则,此行为就与 nx_packet_allocate 完全相同。

参数

  • session_ptr:指向 TLS 会话实例的指针。
  • pool_ptr:指向要从中分配数据包的 NX_PACKET_POOL 的指针。
  • packet_ptr:指向新分配的数据包的输出指针。
  • wait_option:用于数据包分配的挂起选项。

返回值

  • NX_SUCCESS (0x00):成功分配数据包。
  • NX_SECURE_TLS_ALLOCATE_PACKET_FAILED (0X111):基础数据包分配失败。
  • NX_SECURE_TLS_SESSION_UNINITIALIZED (0x101):提供的 TLS 会话未初始化。

允许来自

线程数

示例

/* Allocate a new TLS packet from the previously created packet pool and
previously initialized TLS session.   */

status = nx_secure_tls_packet_allocate(&tls_session, &pool_0, &packet_ptr,
                                       NX_WAIT_FOREVER);

/* If status is NX_SUCCESS, the newly allocated packet pointer is found in the
variable packet_ptr.  */

另请参阅

  • nx_tcp_socket_receive
  • nx_secure_x509_certificate_initialize
  • nx_secure_tls_remote_certificate_allocate
  • nx_secure_tls_session_start
  • nx_secure_tls_session_delete
  • nx_secure_tls_session_receive
  • nx_secure_tls_session_send
  • nx_secure_tls_session_end
  • nx_secure_tls_session_create

nx_secure_tls_psk_add

向 NetX Secure TLS 会话添加预共享密钥

原型

UINT  nx_secure_tls_psk_add(NX_SECURE_TLS_SESSION *session_ptr,
                            UCHAR *pre_shared_key, UINT psk_length,
                            UCHAR *psk_identity, UINT
                            identity_length, UCHAR *hint, UINT
                            hint_length);

说明

此服务向 TLS 会话控制块添加预共享密钥 (PSK)、其标识字符串和标识提示。 如果启用并使用 PSK 密码套件,则会用 PSK 来代替数字证书。

参数

  • session_ptr:指向之前创建的 TLS 会话实例的指针。
  • pre_shared_key:实际的 PSK 值。
  • psk_length:PSK 值的长度。
  • psk_identity:用于标识此 PSK 值的字符串。
  • identity_length:PSK 标识的长度。
  • hint:用于表示要从 TLS 服务器上选择的 PSK 组的字符串。
  • hint_length:提示字符串的长度。

返回值

  • NX_SUCCESS (0X00):成功添加 PSK。
  • NX_PTR_ERROR (0X07):TLS 会话指针无效。
  • NX_SECURE_TLS_NO_MORE_PSK_SPACE (0X125):不能再添加一个 PSK。

允许来自

线程数

示例

/* PSK value.  */
UCHAR psk[] = { 0x1a, 0x2b, 0x3c, 0x4d };

/* Add PSK to TLS session.  */
status =  nx_secure_tls_psk_add(&tls_session, psk, sizeof(psk), “psk_1”, 4,
“Client_identity”, 15);


/* If status is NX_SUCCESS the PSK was successfully added.  */

另请参阅

  • nx_secure_tls_client_psk_set
  • nx_secure_x509_certificate_initialize
  • nx_secure_tls_session_create
  • nx_secure_tls_remote_certificate_allocate
  • nx_secure_tls_local_certificate_add

nx_secure_tls_remote_certificate_allocate

为远程 TLS 主机提供的证书分配空间

原型

UINT  nx_secure_tls_remote_certificate_allocate(
                 NX_SECURE_TLS_SESSION *session_ptr,
                 NX_SECURE_X509_CERT *certificate_ptr,
                 UCHAR *raw_certificate_buffer,
                 UINT raw_buffer_size);

说明

此服务将未初始化的 NX_SECURE_X509_CERT 结构实例添加到 TLS 会话,目的是为在 TLS 会话期间由远程主机提供的证书分配空间。 NetX Secure TLS 会分析远程证书数据,并将此信息用于填充提供给此函数的证书结构实例。 以这种方式添加的证书将放置在链接列表中。

如果预计远程主机将提供多个证书,则应重复调用此函数,以便为所有证书分配空间。 系统会将其他证书添加到证书链接列表的末尾。

如果无法分配远程证书,则会导致 TLS 客户端模式在 TLS 握手期间失败,除非使用了预共享密钥 (PSK) 密码套件。

raw_certificate_buffer 参数指向分配用于存储传入远程证书的空间。 使用 SHA-256 进行签名且具有 2048 位 RSA 密钥的典型证书的范围为 1000-2000 字节。 缓冲区应该足够大,至少可以容纳该大小,但由于远程主机不同,证书可能明显更小或更大。 请注意,如果缓冲区太小,无法保存传入的证书,TLS 握手将以错误结束。

对于 TLS 服务器模式,仅当启用客户端证书身份验证时,才需要远程证书分配。

参数

  • session_ptr:指向之前创建的 TLS 会话实例的指针。
  • certificate_ptr:指向已初始化的 X.509 证书实例的指针。
  • raw_certificate_buffer:指向用于保存从远程主机收到的未分析证书的缓冲区的指针。
  • raw_buffer_size:原始证书缓冲区的大小。

返回值

  • NX_SUCCESS (0X00):成功分配证书。
  • NX_PTR_ERROR (0X07):TLS 会话指针无效。
  • NX_SECURE_TLS_INSUFFICIENT_CERT_SPACE (0x12D):提供的缓冲区太小。
  • NX_INVALID_PARAMETERS (0X4D):尝试添加的证书无效。

允许来自

线程数

示例

/* Certificate control block. */
NX_SECURE_X509_CERT certificate;

/* Buffer space to hold the incoming certificate. */
UCHAR certificate_buffer[2000];

/* Add certificate to TLS session.  */
status =  nx_secure_tls_remote_certificate_allocate(&tls_session, &certificate,
                                                    certificate_buffer,
                                                    sizeof(certificate_buffer));


/* If status is NX_SUCCESS the certificate was successfully allocated.  */

另请参阅

  • nx_secure_x509_certificate_initialize,
  • nx_secure_tls_session_create

nx_secure_tls_remote_certificate_buffer_allocate

为远程 TLS 主机提供的所有证书分配空间

原型

UINT  nx_secure_tls_remote_certificate_buffer_allocate(
                  NX_SECURE_TLS_SESSION *session_ptr,
                  UINT certs_number, VOID *certificate_buffer,
                  ULONG buffer_size);

说明

此服务用于分配处理从远程服务器主机传入的证书链所需的空间,以便在 TLS 客户端实例中执行 X.509 身份验证和验证。 对于 TLS 服务器模式,仅在启用了客户端 X.509 证书身份验证时,才需要远程证书分配。对于 TLS 服务器实例,应改为使用服务 nx_secure_tls_session_x509_client_verify_configure。

如果无法分配远程证书,则会导致 TLS 客户端模式在 TLS 握手期间失败,除非使用了预共享密钥 (PSK) 密码套件。

certificate_buffer 参数指向分配用于存储传入远程证书和这些证书所需的控制块的空间。 系统将根据证书数量 (certs_number) 划分缓冲区,并为每个证书指定等量的部分。 buffer_size 参数表示缓冲区的大小。 可以通过以下公式找到所需的空间:

buffer_size = (<expected max number of certificates in chain>) *
                 (sizeof(NX_SECURE_X509_CERT) + <max cert size>)

使用 SHA-256 进行签名且具有 2048 位 RSA 密钥的典型证书的范围为 1000-2000 字节。 缓冲区应该足够大,其大小至少可以容纳每个证书,但由于远程主机不同,证书可能明显更小或更大。 请注意,如果缓冲区太小,无法保存传入的证书,TLS 握手将以错误结束。

参数

  • session_ptr:指向之前创建的 TLS 会话实例的指针。
  • certs_number:要从提供的缓冲区中分配的证书的数量。
  • certificate_buffer:指向用于保存从远程主机接收的证书的缓冲区的指针。
  • buffer_size:证书缓冲区的大小。

返回值

  • NX_SUCCESS (0X00):成功分配证书。
  • NX_PTR_ERROR (0X07):TLS 会话或缓冲区指针无效。
  • NX_SECURE_TLS_INSUFFICIENT_CERT_SPACE (0x12D):提供的缓冲区太小。
  • NX_INVALID_PARAMETERS (0x4D):缓冲区太小,无法容纳所需数量的证书。

允许来自

线程数

示例

/* Buffer space to hold the incoming certificates. */
#define CERTIFICATE_NUMBER    (2)
#define CERTIFICATE_SIZE      (2000)
#define BUFFER_SIZE           (CERTIFICATE_NUMBER * \
                              (sizeof(NX_SECURE_X509_CERT) + CERTIFICATE_SIZE))
UCHAR certificate_buffer[BUFFER_SIZE];

/* Add certificate to TLS session.  */
status =  nx_secure_tls_remote_certificate_buffer_allocate(&tls_session,
                                                      CERTIFICATE_NUMBER,
                                                      certificate_buffer,
                                                      BUFFER_SIZE);


/* If status is NX_SUCCESS the buffer was successfully allocated.  */

另请参阅

  • nx_secure_x509_certificate_initialize
  • nx_secure_tls_session_create

nx_secure_tls_remote_certificate_free_all

释放为传入证书分配的空间

原型

UINT  nx_secure_tls_remote_certificate_free_all(
                  NX_SECURE_TLS_SESSION *session_ptr);

说明

此服务用于释放通过 nx_secure_tls_remote_certificate_allocated 分配给特定 TLS 会话的所有证书缓冲区,方法是将这些空间返回到该会话的可用证书空间。 如果应用程序重复使用 TLS 会话对象,而不使用 nx_secure_tls_session_delete 删除此对象以及使用 nx_secure_tls_session_create 重新创建此对象,则需要使用此服务。

请注意,在 nx_secure_tls_session_end 中重置 TLS 会话时,远程证书空间会自动恢复,因此大多数应用程序不需要调用此服务。

参数

  • session_ptr:指向之前创建的 TLS 会话实例的指针。

返回值

  • NX_SUCCESS (0x00):操作成功。
  • NX_PTR_ERROR (0X07):TLS 会话指针无效。
  • NX_INVALID_PARAMETERS (0X4D):内部错误 - 证书存储可能已损坏。

允许来自

线程数

示例

/* Certificate control block. */
NX_SECURE_X509_CERT certificate;

/* Buffer space to hold the incoming certificate. */
UCHAR certificate_buffer[2000];

/* Add certificate to TLS session.  */
status =  nx_secure_tls_remote_certificate_allocate(&tls_session, &certificate,
                                                    certificate_buffer,
                                                    sizeof(certificate_buffer));


/* If status is NX_SUCCESS the certificate was successfully allocated.  */

/* … TLS session setup, TCP connection, etc… */

/* End TLS session. */
nx_secure_tls_session_end(&tls_session, NX_WAIT_FOREVER);

/* Free up certificate buffers for next connection. */
nx_secure_tls_remote_certificate_free_all(&tls_session);

另请参阅

  • nx_secure_x509_certificate_initialize
  • nx_secure_tls_session_create
  • nx_secure_tls_remote_certificate_allocate
  • nx_secure_tls_session_end

nx_secure_tls_server_certificate_add

使用数字标识符添加专门用于 TLS 服务器的证书

原型

UINT  nx_secure_tls_server_certificate_add(
                  NX_SECURE_TLS_SESSION *session_ptr,
                  NX_SECURE_X509_CERT *certificate, UINT cert_id);

说明

此服务用于使用数字标识符将证书添加到 TLS 会话的本地存储(请参阅 nx_secure_tls_local_certificate_add),而不是使用证书中的 X.509 使用者(公用名)为存储编制索引。 将数字标识符与证书分开后,即可将多个证书作为身份证书添加到 TLS 服务器,还可将具有相同公用名的多个证书添加到同一个 TLS 会话本地存储中。 可将此相同服务用于客户端证书,但 TLS 客户端很少具有多个标识证书。

cert_id 参数是由应用程序分配的非零正整数。 实际值并不重要(零除外),但在所提供的 TLS 会话的存储中必须唯一。 cert_id 值可用于分别使用 nx_secure_tls_server_certificate_find 和 nx_secure_tls_server_certificate_remove 在本地存储区中查找和删除证书。

重要

使用 nx_secure_tls_local_certificate_add 时,不应将此 API 用于同一个 TLS 会话。 nx_secure_tls_server_certificate_add API 对每个证书使用唯一的数字标识符,而本地证书服务基于 X.509 公用名编制索引。 服务器证书服务允许具有共享数据(特别是公用名)的多个证书存在于同一个本地存储区中,这对具有多个标识的服务器非常有用。

参数

  • session_ptr:指向之前创建的 TLS 会话实例的指针。
  • certificate:指向之前初始化的 X.509 证书实例的指针。
  • cert_id:正数、非零、相对唯一的证书 ID 号。

返回值

  • NX_SUCCESS (0x00):操作成功。
  • NX_PTR_ERROR (0X07):TLS 会话或证书指针无效。
  • NX_SECURE_TLS_CERT_ID_INVALID (0x138):提供的证书 ID 具有无效值(可能为 0)。
  • NX_SECURE_TLS_CERT_ID_DUPLICATE (0x139):提供的证书 ID 在本地存储中已存在。
  • NX_INVALID_PARAMETERS (0X4D):内部错误 - 证书存储可能已损坏。

允许来自

线程数

示例

/* Certificate control block. */
NX_SECURE_X509_CERT certificate;


/* Add certificate to TLS session.  */
status =  nx_secure_tls_server_certificate_add(&tls_session, &certificate, 0x12);


/* If status is NX_SUCCESS the certificate was successfully added with the ID
0x12.  */

另请参阅

  • nx_secure_x509_certificate_initialize
  • nx_secure_tls_local_certificate_add
  • nx_secure_tls_active_certificate_set
  • nx_secure_tls_server_certificate_find
  • nx_secure_tls_server_certificate_remove

nx_secure_tls_server_certificate_find

使用数字标识符查找证书

原型

UINT  nx_secure_tls_server_certificate_find(
                  NX_SECURE_TLS_SESSION *session_ptr,
                  NX_SECURE_X509_CERT **certificate, UINT cert_id);

说明

此服务用于使用数字标识符在 TLS 会话的本地存储(请参阅 nx_secure_tls_local_certificate_add)中查找证书,而不是使用证书中的 X.509 使用者(公用名)为存储编制索引。

cert_id 参数是使用 nx_secure_tls_server_certificate_add 将证书添加到 TLS 会话本地存储时,由应用程序分配的非零正整数。

重要

使用 nx_secure_tls_local_certificate_add 时,不应将此 API 用于同一个 TLS 会话。 nx_secure_tls_server_certificate_add API 对每个证书使用唯一的数字标识符,而本地证书服务基于 X.509 公用名编制索引。 服务器证书服务允许具有共享数据(特别是公用名)的多个证书存在于同一个本地存储区中,这对具有多个标识的服务器非常有用。

参数

  • session_ptr:指向之前创建的 TLS 会话实例的指针。
  • certificate:指向 X.509 证书指针的指针,用于返回对找到的证书的引用。
  • cert_id:非零正数证书 ID 值。

返回值

  • NX_SUCCESS (0x00):操作成功。
  • NX_PTR_ERROR (0X07):TLS 会话或证书指针无效。
  • NX_SECURE_TLS_CERTIFICATE_NOT_FOUND (0x119):提供的证书 ID 与所提供的 TLS 会话的本地存储中的任何值都不匹配。

允许来自

线程数

示例

NX_SECURE_X509_CERT *certificate;


/* Find certificate in TLS session.  */
status =  nx_secure_tls_server_certificate_find(&tls_session, &certificate, 0x12);


/* If status is NX_SUCCESS the certificate was successfully found and a reference
returned in the certificate parameter.  */

另请参阅

  • nx_secure_x509_certificate_initialize
  • nx_secure_tls_local_certificate_add
  • nx_secure_tls_active_certificate_set
  • nx_secure_tls_server_certificate_add
  • nx_secure_tls_server_certificate_remove

nx_secure_tls_server_certificate_remove

使用数字标识符删除本地服务器证书

原型

UINT  nx_secure_tls_server_certificate_remove(
                  NX_SECURE_TLS_SESSION *session_ptr, UINT cert_id);

说明

此服务用于使用数字标识符从 TLS 会话的本地存储(请参阅 nx_secure_tls_local_certificate_add)中删除证书,而不是使用证书中的 X.509 使用者(公用名)为存储编制索引。

cert_id 参数是使用 nx_secure_tls_server_certificate_add 将证书添加到 TLS 会话本地存储时,由应用程序分配的非零正整数。

参数

  • session_ptr:指向之前创建的 TLS 会话实例的指针。
  • cert_id:非零正数证书 ID 值。

返回值

  • NX_SUCCESS (0x00):操作成功。
  • NX_PTR_ERROR (0X07):TLS 会话无效。
  • NX_SECURE_TLS_CERTIFICATE_NOT_FOUND (0x119):提供的证书 ID 与所提供的 TLS 会话的本地存储中的任何值都不匹配。

允许来自

线程数

示例

/* Certificate control block. */
NX_SECURE_X509_CERT certificate;


/* Add certificate to TLS session with id 0x12.  */
status =  nx_secure_tls_server_certificate_add(&tls_session, &certificate, 0x12);
/* Use certificate in TLS session, etc… */

/* Remove certificate from TLS session with id 0x12.  */
status =  nx_secure_tls_server_certificate_remove(&tls_session, 0x12);


/* If status is NX_SUCCESS the certificate was successfully removed.  */

另请参阅

  • nx_secure_x509_certificate_initialize
  • nx_secure_tls_local_certificate_add
  • nx_secure_tls_active_certificate_set
  • nx_secure_tls_server_certificate_add
  • nx_secure_tls_server_certificate_find

nx_secure_tls_session_alert_value_get

获取远程主机发送的 TLS 警报值和级别

原型

UINT  nx_secure_tls_session_alert_value_get(
                   NX_SECURE_TLS_SESSION *session_ptr,
                   UINT *alert_level, UINT *alert_value);

说明

此服务用于在远程主机发送警报以响应某些问题或错误时检索 TLS 警报级别和值。

alert_level 和 alert_value 参数的值只在以下情况下有效:TLS API 调用返回 NX_SECURE_TLS_ALERT_RECEIVED (0x114) 状态后立即调用此函数,这表示已从远程主机收到警报。

请注意,如果本地主机 TLS 发送警报,返回的错误代码比 TLS 警报本身更能说明实际错误,因为 TLS 警报值特意采用不明确的说明,旨在防止遭受某些类型的攻击(例如“padding oracle”攻击或类似攻击)。

警报级别仅使用以下两个值之一:NX_SECURE_TLS_ALERT_LEVEL_WARNING (0x1) 或 NX_SECURE_TLS_ALERT_LEVEL_FATAL (0x2)。 通常情况下,尽管某些扩展配置情况也可以视为警告,但只有 CloseNotify 警报(用于表示 TLS 会话已成功结束)被指定为“警告”级别。 绝大多数警报都是“严重”,这表示可能存在安全故障,会导致 TLS 连接(握手或会话)立即关闭。

TLS 警报值在 TLS RFC 中定义,以下是供你参考的 RFC 5246 (TLSv1.2) 的列表:

警报名称 “值” 说明
close_notify 0 无错误,表示会话成功结束
unexpected_message 10 TLS 收到意外或无序的消息
bad_record_mac 20 解密和/或 MAC 验证失败
decryption_failed_RESERVED 21 已弃用:解密失败(由于受到 padding oracle 攻击而被弃用)
record_overflow 22 收到的记录大于 TLS 最大大小的记录
decompression_failure 30 在压缩/解压缩 TLS 记录时遇到问题
handshake_failure 40 出现了一些其他警报未涵盖的未指定握手错误
no_certificate_RESERVED 41 在 TLS 中已弃用(仅限 SSL)
bad_certificate 42 收到的证书包含无效的格式或签名
unsupported_certificate 43 收到的证书的类型无效(例如,用于 TLS 服务器身份验证的只有签名的证书)
certificate_revoked 44 证书状态(由 CRL 或 OCSP 提供)已标示为“已吊销”
certificate_expired 45 收到的证书已超出其有效的日期范围(无效或已过期)
certificate_unknown 46 遇到了一些其他警报未涵盖的未知证书问题
illegal_parameter 47 TLS 握手中的某些配置或协商值无效或超出范围
unknown_ca 48 收到的标识证书无法通过证书链跟踪到受信任的根 CA 证书。
access_denied 49 表示收到了有效证书,但应用程序访问控制指出该证书对请求的资源无效。
decode_error 50 TLS 标头或握手消息中的某些字段或值已超出范围或无效,导致 TLS 记录解码失败。
decrypt_error 51 无法验证 TLS 握手期间的签名或已完成的消息哈希。
export_restriction_RESERVED 60 在 TLSv1.2 中已弃用
protocol_version 70 系统已识别出握手期间协商的 TLS 协议版本,但不支持此版本(例如,提供了 TLSv1.0,但未启用)。
insufficient_security 71 在由于缺少安全密码而导致握手失败时发送(例如,密钥大小对于应用程序要求而言太小)
internal_error 80 出现一些非 TLS 错误(例如,内存分配问题和应用程序问题),导致 TLS 会话中断。
user_canceled 90 在用户或应用程序在握手完成之前取消 TLS 会话时返回(类似于 CloseNotify)。
no_renegotiation 100 表示远程主机不愿意执行 TLS 重新协商握手来响应重新协商请求。
unsupported_extension 110 在 TLS 客户端收到包含在初始 ClientHello 中未明确要求的扩展名的 ServerHello 时发送(表示服务器有问题)。

参数

  • session_ptr:指向 TLS 会话实例的指针。
  • alert_level:返回收到的警报的级别(警告或严重)。
  • alert_value:返回收到的警报的值(请参阅表)。

返回值

  • NX_SUCCESS (0x00):操作成功。
  • NX_PTR_ERROR (0X07):TLS 会话无效。

允许来自

线程数

示例

/* Return values. */
UINT status, alert_level, alert_value;


/* Start a TLS session.  */
status =  nx_secure_tls_session_start(&tls_session, &tcp_socket, NX_WAIT_FOREVER);

/* Check for “alert received” error. */
if(status == NX_SECURE_TLS_ALERT_RECEIVED)
{

        /* Get the alert level and value. */
        status =  nx_secure_tls_session_alert_value_get(&tls_session,
                                             &alert_level, &alert_value);

        /* Print out the received alert level and value. */
        printf("Alert recieved. Value: %d, Level: %d\n", alert_value,
                alert_level);
}
else if(status != NX_SUCCESS)
{
    /* Additional error handling. */
}

另请参阅

  • nx_secure_tls_session_start
  • nx_secure_tls_session_send
  • nx_secure_tls_session_receive

nx_secure_tls_session_certificate_callback_set

为 TLS 设置用于附加证书验证的回调

原型

UINT  nx_secure_tls_ session_certificate_callback_set (
                  NX_SECURE_TLS_SESSION *tls_session,
                  ULONG (*func_ptr)(NX_SECURE_TLS_SESSION *session,
                                    NX_SECURE_X509_CERT *certificate));

说明

此服务向 TLS 会话分配一个函数指针,TLS 将在从远程主机收到证书时调用此会话,使应用程序能够执行验证检查,例如 DNS 验证、证书吊销和证书策略实施。

NetX Secure TLS 将在调用回调之前对证书执行基本的 X.509 路径验证,以确保可以根据此证书跟踪到 TLS 受信任的证书存储中的证书,但所有其他验证都将由此回调处理。

回调提供 TLS 会话指针和指向远程主机标识证书的指针(证书链中的叶)。 如果所有验证都成功,则回调应返回 NX_SUCCESS,否则,该回调应返回表示验证失败的错误代码。 除 NX_SUCCESS 之外的任何值都将导致 TLS 握手立即中止。

参数

  • session_ptr:指向之前创建的 TLS 会话实例的指针。
  • func_ptr:指向证书验证回调函数的指针。

返回值

  • NX_SUCCESS (0X00):成功分配函数指针。
  • NX_PTR_ERROR (0X07):TLS 会话指针无效。

允许来自

线程数

示例

/* Callback routine used to perform additional checks on a certificate. */
ULONG certificate_callback(NX_SECURE_TLS_SESSION *session, NX_SECURE_X509_CERT
*certificate)
{
    /* Certificate validation checking goes here. */
    return(NX_SUCCESS);
}

/* In TLS setup routine. */
{
        /* Add callback to TLS session.  */
        status =  nx_secure_tls_session_certificate_callback_set(&tls_session,
                                                            certificate_callback);

        /* If status is NX_SUCCESS the certificate callback was added.  */
}

另请参阅

  • nx_secure_tls_session_create
  • nx_secure_x509_common_name_dns_check
  • nx_secure_x509_crl_revocation_check

nx_secure_tls_session_client_callback_set

为 TLS 设置在 TLS 客户端握手开始时调用的回调

原型

UINT  nx_secure_tls_ session_client_callback_set (
                  NX_SECURE_TLS_SESSION *tls_session,
                  ULONG (*func_ptr)(NX_SECURE_TLS_SESSION *tls_session,
                                    NX_SECURE_TLS_HELLO_EXTENSION
                                    *extensions, UINT num_extensions));

说明

此服务将函数指针分配给 TLS 会话,当 TLS 客户端握手收到 ServerHelloDone 消息时,TLS 将调用该会话。 使用此回调函数,应用程序可以处理收到的 ServerHello 消息中需要输入或决策的任何 TLS 扩展。

系统通过调用 TLS 会话控制块和 NX_SECURE_TLS_HELLO_EXTENSION 对象的数组来执行此回调。 扩展对象的数组应该传递到一个帮助程序函数,该函数将查找并分析特定扩展。 目前,NetX Secure 不支持需要 TLS 客户端输入的特定扩展,但应用程序设计人员可以通过回调处理可能变为可用的自定义或新扩展。 有关分析 hello 消息中提供的 TLS 扩展的示例帮助程序函数,请参阅 nx_secure_tls_session_sni_extension_parse。

如果远程服务器已请求证书,并提供了可供 TLS 客户端选择特定证书的信息,还可以使用客户端回调通过 nx_secure_tls_active_certificate_set 为 TLS 客户端选择活动标识证书。 有关详细信息,请参阅 nx_secure_tls_active_certificate_set 的引用。

参数

  • session_ptr:指向之前创建的 TLS 会话实例的指针。
  • func_ptr:指向 TLS 客户端回调函数的指针。

返回值

  • NX_SUCCESS (0X00):成功分配函数指针。
  • NX_PTR_ERROR (0X07):TLS 会话指针无效。

允许来自

线程数

示例

/* Callback routine used to process ServerHello extensions and perform other
   runtime actions at the beginning of a TLS handshake (such as selecting an
   identify certificate to provide to the server). */

ULONG tls_client_callback(NX_SECURE_TLS_SESSION *session,
                          NX_SECURE_TLS_HELLO_EXTENSION *extensions, UINT
                          num_extensions)
{

    /* Extension parsing would go here. */

    /* Set an active identity certificate – the certificate should have been added
       to the local store at application start with
       nx_secure_tls_local_certificate_add. */
    nx_secure_tls_active_certificate_set(session, &global_identity_certificate);

    return(NX_SUCCESS);
}

/* TLS setup routine. */
UINT tls_setup(NX_SECURE_TLS_SESSION *tls_session)
{
    /* Add callback to TLS session.  */
    status =  nx_secure_tls_session_client_callback_set(tls_session,
                                                        client_callback);

    /* If status is NX_SUCCESS the callback was added and will be invoked once
       a ServerHelloDone message is received. */

    return(status);
}

另请参阅

  • nx_secure_tls_session_create
  • nx_secure_tls_session_server_callback_set
  • nx_secure_tls_active_certificate_set

nx_secure_tls_session_x509_client_verify_configure

启用客户端 X.509 验证并为客户端证书分配空间

原型

UINT  nx_secure_tls_session_x509_client_verify_configure(
                  NX_SECURE_TLS_SESSION *session_ptr,
                  UINT certs_number, VOID *certificate_buffer,
                  ULONG buffer_size);

说明

此服务用于为 TLS 服务器实例启用可选的 X.509 客户端身份验证。 它还会分配从远程客户端主机处理传入的证书链所需的空间。 远程客户端提供的证书将根据 TLS 服务器实例的受信任证书进行验证,并使用服务 nx_secure_tls_trusted_certificate_add 进行分配。

在 TLS 客户端模式下,需要使用远程证书分配,应改为使用服务 nx_secure_tls_remote_certificate_buffer_allocate。 为 TLS 客户端实例启用 X.509 客户端身份验证将不起作用。

certificate_buffer 参数指向分配用于存储传入远程证书和这些证书所需的控制块的空间。 系统将根据证书数量 (certs_number) 划分缓冲区,并为每个证书指定等量的部分。 buffer_size 参数表示缓冲区的大小。 可以通过以下公式找到所需的空间:

buffer_size = (<expected max number of certificates in chain>) *
             (sizeof(NX_SECURE_X509_CERT) + <max cert size>)

使用 SHA-256 进行签名且具有 2048 位 RSA 密钥的典型证书的范围为 1000-2000 字节。 缓冲区应该足够大,其大小至少可以容纳每个证书,但由于远程主机不同,证书可能明显更小或更大。 请注意,如果缓冲区太小,无法保存传入的证书,TLS 握手将以错误结束。

参数

  • session_ptr:指向之前创建的 TLS 会话实例的指针。
  • certs_number:要从提供的缓冲区中分配的证书的数量。
  • certificate_buffer:指向用于保存从远程主机接收的证书的缓冲区的指针。
  • buffer_size:证书缓冲区的大小。

返回值

  • NX_SUCCESS (0X00):成功分配证书。
  • NX_PTR_ERROR (0X07):TLS 会话或缓冲区指针无效。
  • NX_SECURE_TLS_INSUFFICIENT_CERT_SPACE (0x12D):提供的缓冲区太小。
  • NX_INVALID_PARAMETERS (0x4D):缓冲区太小,无法容纳所需数量的证书。

允许来自

线程数

示例

/* Buffer space to hold the incoming certificates. */
#define CERTIFICATE_NUMBER    (2)
#define CERTIFICATE_SIZE      (2000)
#define BUFFER_SIZE          (CERTIFICATE_NUMBER * \
                                (sizeof(NX_SECURE_X509_CERT) + CERTIFICATE_SIZE))
UCHAR certificate_buffer[BUFFER_SIZE];

/* Enable X.509 Client verification and allocate certificate space in our TLS
   Server session.  */
status =  nx_secure_tls_session_x509_client_verify_configure(&tls_session,
                                                    CERTIFICATE_NUMBER,
                                                    certificate_buffer,
                                                    BUFFER_SIZE);


/* If status is NX_SUCCESS the buffer was successfully allocated.  */

另请参阅

  • nx_secure_x509_certificate_initialize
  • nx_secure_tls_session_create
  • nx_secure_tls_remote_certificate_buffer_allocate

nx_secure_tls_session_client_verify_disable

为 NetX Secure TLS 会话禁用客户端证书身份验证

原型

UINT  nx_secure_tls_session_client_verify_disable(
                              NX_SECURE_TLS_SESSION *session_ptr);

说明

此服务用于为特定 TLS 会话禁用客户端证书身份验证。 有关详细信息,请参阅 nx_secure_tls_session_client_verify_enable。

参数

  • session_ptr:指向 TLS 会话实例的指针。

返回值

  • NX_SUCCESS (0X00):成功更改了状态。
  • NX_PTR_ERROR (0X07):TLS 会话指针无效。

允许来自

线程数

示例

/* Disable client certificate authentication for this TLS session.   */
status = nx_secure_tls_session_client_verify_disable(&tls_session);

/* Any new TLS Server sessions using the tls_session control block will not
request certificates from the remote TLS client.  */

另请参阅

  • nx_secure_tls_session_client_verify_enable
  • nx_secure_tls_session_start
  • nx_secure_tls_session_create

nx_secure_tls_session_client_verify_enable

为 NetX Secure TLS 会话启用客户端证书身份验证

原型

UINT  nx_secure_tls_session_client_verify_enable(
                                NX_SECURE_TLS_SESSION *session_ptr);

说明

此服务用于为特定 TLS 会话启用客户端证书身份验证。 为 TLS 服务器实例启用客户端证书身份验证,将导致 TLS 服务器在初始 TLS 握手期间从任何远程 TLS 客户端请求证书。 从远程 TLS 客户端收到的证书附带了 CertificateVerify 消息,TLS 服务器使用该消息验证客户端拥有的证书(是否有权访问与该证书相关联的私钥)。

如果可以通过 X.509 证书链验证提供的证书并根据此证书跟踪到 TLS 服务器受信任的证书存储区中的证书,则会对远程 TLS 客户端进行身份验证,并继续执行握手。 如果在处理证书或 CertificateVerify 消息时出现任何错误,TLS 握手将以错误结束。

注意

TLS 服务器的受信任存储区中必须至少包含一个使用 nx_secure_tls_trusted_certificate_add 添加的证书,否则身份验证将始终失败。

参数

  • session_ptr:指向 TLS 会话实例的指针。

返回值

  • NX_SUCCESS (0X00):成功更改了状态。
  • NX_PTR_ERROR (0X07):TLS 会话指针无效。

允许来自

线程数

示例

/* Add a trusted certificate so the TLS Server has something to verify against. */
status = nx_secure_tls_trusted_certificate_add(&tls_session,
                                               &trusted_certificate);

/* Disable client certificate authentication for this TLS session.   */
status = nx_secure_tls_session_client_verify_enable(&tls_session);

/* Any new TLS Server sessions using the tls_session control block will now
request and verify certificates from the remote TLS client.  */

另请参阅

  • nx_secure_tls_session_client_verify_enable
  • nx_secure_tls_session_start
  • nx_secure_tls_session_create
  • nx_secure_tls_trusted_certificate_add

nx_secure_tls_session_create

创建用于安全通信的 NetX Secure TLS 会话

原型

UINT  nx_secure_tls_session_create(NX_SECURE_TLS_SESSION *session_ptr
                                   NX_SECURE_TLS_CRYPTO *cipher_table,
                                   VOID *encryption_metadata_area,
                                   ULONG encryption_metadata_size);

说明

此服务用于初始化 NX_SECURE_TLS_SESSION 结构实例,用于通过网络连接建立安全的 TLS 通信。

此方法采用 NX_SECURE_TLS_CRYPTO 对象,该对象将用为 TLS 提供的可用加密方法进行填充。 encryption_metadata_area 指向分配给 TLS 使用的缓冲区,用于存储 NX_SECURE_TLS_CRYPTO 表中用于计算的加密方法使用的“元数据”。 表的大小可以使用 nx_secure_tls_metadata_size_calculate 服务来确定。 有关更多详细信息,请参阅第 3 章中的“NetX Secure TLS 中的加密”部分。

参数

  • session_ptr:指向 TLS 会话实例的指针。
  • cipher_table:指向 TLS 加密方法的指针。
  • encryption_metadata_area:指向加密元数据所在空间的指针。
  • encryption_metadata_size:元数据缓冲区的大小。

返回值

  • NX_SUCCESS (0X00):成功初始化 TLS 会话。
  • NX_PTR_ERROR (0X07):尝试使用的指针无效。
  • NX_INVALID_PARAMETERS (0x4D):对于给定的方法,元数据缓冲区太小。
  • NX_SECURE_TLS_UNSUPPORTED_CIPHER (0x106):密码表中未提供启用 TLS 版本所需的密码方法。

允许来自

线程数

示例

/* Reference the platform-specific TLS cryptographic method table. */
extern const NX_SECURE_TLS_CRYPTO nx_crypto_tls_ciphers;

/* Declare a buffer for the cryptographic metadata. The size should be calculated
   using nx_secure_tls_metadata_size_calculate. */
UCHAR crypto_metadata[4500];

/* Initialize TLS session.  */
status =  nx_secure_tls_session_create(&tls_session,
                                       &nx_crypto_tls_ciphers,
                                       crypto_metadata,
                                       sizeof(crypto_metadata));


/* If status is NX_SUCCESS the TLS Session was successfully initialized.  */

另请参阅

  • nx_secure_x509_certificate_initialize
  • nx_secure_tls_metadata_size_calculate
  • nx_secure_tls_remote_certificate_allocate
  • nx_secure_tls_session_start
  • nx_secure_tls_session_end
  • nx_secure_tls_session_send
  • nx_secure_tls_session_receive
  • nx_secure_tls_session_delete
  • 第 3 章中的“NetX Secure TLS 中的加密”

nx_secure_tls_session_delete

删除 NetX Secure TLS 会话

原型

UINT  nx_secure_tls_session_delete(NX_SECURE_TLS_SESSION *session_ptr);

说明

此服务用于删除用 NX_SECURE_TLS_SESSION 结构实例表示的 TLS 会话,并释放该会话实例拥有的所有系统资源。

参数

  • session_ptr:指向 TLS 会话实例的指针。

返回值

  • NX_SUCCESS (0X00):成功初始化 TLS 会话。
  • NX_PTR_ERROR (0X07):尝试使用的指针无效。

允许来自

线程数

示例

/* Delete TLS session.  */
status =  nx_secure_tls_session_delete(&tls_session);


/* If status is NX_SUCCESS the TLS Session was successfully deleted.  */

另请参阅

  • nx_secure_x509_certificate_initialize
  • nx_secure_tls_remote_certificate_allocate
  • nx_secure_tls_session_start
  • nx_secure_tls_session_end
  • nx_secure_tls_session_send
  • nx_secure_tls_session_receive
  • nx_secure_tls_session_create

nx_secure_tls_session_end

结束活动的 NetX Secure TLS 会话

原型

UINT  nx_secure_tls_session_end(NX_SECURE_TLS_SESSION *session_ptr,
                                    ULONG wait_option);

说明

此服务用于结束用 NX_SECURE_TLS_SESSION 结构实例表示的 TLS 会话,方法是将 TLS CloseNotify 消息发送到远程主机。 然后,该服务会等待远程主机响应自己的 CloseNotify 消息。

如果远程主机未发送 CloseNotify 消息,TLS 就会认为这是一个错误,可能存在安全漏洞,因此检查返回值对于安全连接非常重要。 wait_option 参数可用于控制服务在将控制权返回给调用线程之前应等待响应的时长。

参数

  • session_ptr:指向 TLS 会话实例的指针。
  • wait_option:表示服务应等待远程主机响应的时长。

返回值

  • NX_SUCCESS (0X00):成功初始化 TLS 会话。
  • NX_SECURE_TLS_NO_CLOSE_RESPONSE (0x113):在超时前未收到来自远程主机的响应。
  • NX_SECURE_TLS_ALLOCATE_PACKET_FAILED (0X111):无法分配数据包来发送 CloseNotify 消息。
  • NX_SECURE_TLS_TCP_SEND_FAILED (0X109):无法通过 TCP 套接字发送 CloseNotify 消息。
  • NX_PTR_ERROR (0X07):尝试使用的指针无效。

允许来自

线程数

示例

/* End TLS session.  */
status =  nx_secure_tls_session_end(&tls_session, NX_WAIT_FOREVER);


/* If status is NX_SUCCESS the TLS Session was successfully ended.  */

另请参阅

  • nx_secure_x509_certificate_initialize
  • nx_secure_tls_remote_certificate_allocate
  • nx_secure_tls_session_start
  • nx_secure_tls_session_delete
  • nx_secure_tls_session_send
  • nx_secure_tls_session_receive
  • nx_secure_tls_session_create

nx_secure_tls_session_packet_buffer_set

为 NetX Secure TLS 会话设置数据包重组缓冲区

原型

UINT  nx_secure_tls_session_packet_buffer_set(
                                    NX_SECURE_TLS_SESSION *session_ptr,
                                    UCHAR *buffer_ptr,
                                    ULONG buffer_size);

说明

此服务用于将数据包重组缓冲区与 TLS 会话关联。 为了解密和分析传入的 TLS 记录,系统必须从基础 TCP 数据包组装每个记录中的数据。 TLS 记录的最大大小为 16 KB(但通常要小得多),因此可能不适合单个 TCP 数据包。

如果你知道传入消息的大小将小于 16 KB 的 TLS 记录限制,则可以将缓冲区大小调小,但为了处理未知的传入数据,缓冲区应尽可能大。 如果传入记录超过提供的缓冲区,TLS 会话将以错误结束。

参数

  • session_ptr:指向 TLS 会话实例的指针。
  • buffer_ptr:指向 TLS 用于数据包重组的缓冲区的指针。
  • buffer_size:提供的缓冲区的大小(以字节为单位)。

返回值

  • NX_SUCCESS (0X00):成功初始化 TLS 会话。
  • NX_INVALID_PARAMETERS (0x4D):缓冲区或 TLS 会话指针无效。
  • NX_PTR_ERROR (0X07):尝试使用的指针无效。

允许来自

线程数

示例

/* Buffer for TLS packet reassembly. */
UCHAR tls_packet_buffer[16384];
/* Assign buffer to TLS session.  */
status =  nx_secure_tls_session_packet_buffer_set(&tls_session, tls_packet_buffer,
                                                  sizeof(tls_packet_buffer));


/* If status is NX_SUCCESS the buffer was successfully added.  */

另请参阅

  • nx_secure_x509_certificate_initialize
  • nx_secure_tls_remote_certificate_allocate
  • nx_secure_tls_session_start
  • nx_secure_tls_session_delete
  • nx_secure_tls_session_send
  • nx_secure_tls_session_receive
  • nx_secure_tls_session_create

nx_secure_tls_session_protocol_version_override

覆盖 NetX Secure TLS 会话的默认 TLS 协议版本

原型

UINT  nx_secure_tls_session_protocol_version_override(
                              NX_SECURE_TLS_SESSION *session_ptr,
                              USHORT protocol_version);

说明

此服务用于覆盖特定会话使用的默认(最新)TLS 协议版本。 这样,NetX Secure TLS 即可将较旧版本的 TLS 用于特定的 TLS 会话,无需在编译时禁用较新的 TLS 版本。 这在可能需要与不支持最新版本 TLS 的较早主机通信的应用程序中非常有用。

重要

从 5.11 SP3 版本开始,NetX Secure TLS 支持 RFC 7507(请参阅下面的注释),使用此 API 将默认版本替代成较旧版本都将导致在 ClientHello 中发送回退 SCSV。 如果服务器支持较新的 TLS 版本,并且ClientHello 中包含回退 SCSV,则该服务器将中止 TLS 握手,并发出“不当回退”警报。 仅当替代的版本比已启用的 TLS 版本更旧时,才会发送 SCSV(例如,如果将当前版本替代为 TLS 1.2,则不会发送任何 SCSV)。

protocol_version 参数的有效值是以下宏:NX_SECURE_TLS_VERSION_TLS_1_0、NX_SECURE_TLS_VERSION_TLS_1_1 和 NX_SECURE_TLS_VERSION_TLS_1_2。

宏 NX_SECURE_TLS_DISABLE_TLS_1_1 和 NX_SECURE_TLS_ENABLE_TLS_1_0 可用于控制编译到应用程序中的 TLS 版本。 TLS 1.2 版始终处于启用状态。

请注意,如果远程主机不支持提供的版本,连接将失败。NetX Secure TLS 仅协商提供的替代版本。

重要

RFC 7507:TLS 回退 SCSV。 引入此 RFC 是为了缓解最初由服务器处理协议降级协商不当而拒绝其他有效的 ClientHello 消息而引起的安全问题。 为了与这些旧服务器保持兼容,某些 TLS 客户端应用程序开始与旧版 TLS 重试失败的握手(例如,与 TLS 1.2 握手失败,因此尝试与 TLS 1.1 握手)。 但这种解决方法会带来新的问题,攻击者可能会通过人为引入网络或数据包错误迫使客户端降级,在这种情况下,即使服务器支持较新的 TLS 版本,服务器连接也会失败。 通过降级到较旧的版本,攻击者能够利用此版本中的弱点(SSLv321 特别容易受到 POODLE 攻击)。 为了防止出现这种情况,RFC 7507 引入了“回退 SCSV”,这是在 ClientHello 中发送的伪密码套件22,当 TLS 客户端使用的 TLS 版本并非 TLS 服务器支持的最新版本时,ClientHello 会通知 TLS 服务器。 这样一来,支持较新版本的服务器就可以拒绝包含回退 SCSV 的 ClientHello,并防止降级攻击取得成功。

  1. NetX Secure 未实现 SSLv3,因为存在已知的严重漏洞(例如 POODLE)。

  2. 伪密码套件或 SCSV(Signaling Cipher Suite Value,信号加密套件值)是预留的密码套件号,用于向启用了信号的 TLS 实现发送有关较旧的 TLS 版本中不可用的功能的信号。 回退 SCSV 和 TLS_EMPTY_RENEGOTIATION_INFO_SCSV (RFC 5746) 都是示例。

参数

  • session_ptr:指向 TLS 会话实例的指针。
  • protocol_version:要使用的特定 TLS 版本的 TLS 版本宏。

返回值

  • NX_SUCCESS (0X00):成功更改了状态。
  • NX_PTR_ERROR (0X07):TLS 会话指针无效。
  • NX_SECURE_TLS_UNSUPPORTED_TLS_VERSION (0X110):已知但不支持的 TLS 版本。
  • NX_SECURE_TLS_UNKNOWN_TLS_VERSION (0x10F):协议版本无效。

允许来自

线程数

示例

/* Set the protocol version to be used to TLSv1.1. */
status = nx_secure_tls_session_protocol_version_override(&tls_session,
                                              NX_SECURE_TLS_VERSION_TLS_1_1);

/* This TLS Session will use TLSv1.1 for the handshake and TLS session. */
status = nx_secure_tls_session_start(&tls_session, &tcp_socket, NX_WAIT_FOREVER);

另请参阅

  • nx_secure_tls_session_start
  • nx_secure_tls_session_create

nx_secure_tls_session_receive

接收来自 NetX Secure TLS 会话的数据

原型

UINT  nx_secure_tls_session_receive(NX_SECURE_TLS_SESSION *session_ptr,
                                    NX_PACKET **packet_ptr,
                                    ULONG wait_option);

说明

此服务用于接收来自指定的活动 TLS 会话的数据,处理该数据的解密,然后再将其提供给 NX_PACKET 参数中的调用方。 如果指定的会话中没有数据排队,此调用会根据提供的等待选项而挂起。

重要

如果返回了 NX_SUCCESS,应用程序应负责在不再需要收到的数据包时将其释放。

参数

  • session_ptr:指向 TLS 会话实例的指针。
  • packet_ptr:指向分配的 TLS 数据包指针的指针。
  • wait_option:表示服务在返回之前应等待来自远程主机的数据包的时长。

返回值

  • NX_SUCCESS (0X00):成功初始化 TLS 会话。
  • NX_NO_PACKET (0x01):未收到任何数据。
  • NX_NOT_CONNECTED (0x38):不再连接底层套接字。
  • NX_SECURE_TLS_HASH_MAC_VERIFY_FAILURE (0x108):收到的消息未通过身份验证哈希检查。
  • NX_SECURE_TLS_UNKNOWN_TLS_VERSION (0x10F):收到的消息在其标头中包含未知的协议版本。
  • NX_SECURE_TLS_ALERT_RECEIVED (0X114):收到来自远程主机的 TLS 警报。
  • NX_PTR_ERROR (0X07):尝试使用的指针无效。
  • NX_SECURE_TLS_SESSION_UNINITIALIZED (0x101):提供的 TLS 会话未初始化。

允许来自

线程数

示例

/* Receive a packet from an active TLS session previously created and started with
nx_secure_tls_session_start. Wait until a packet is received, blocking otherwise.
*/
status =  nx_secure_tls_session_receive(&tls_session, &packet_ptr,
NX_WAIT_FOREVER);


/* If status is NX_SUCCESS the received packet is pointed to by  "packet_ptr". */

另请参阅

  • nx_tcp_socket_receive
  • nx_secure_x509_certificate_initialize
  • nx_secure_tls_remote_certificate_allocate
  • nx_secure_tls_session_start
  • nx_secure_tls_session_delete
  • nx_secure_tls_session_send
  • nx_secure_tls_session_end
  • nx_secure_tls_session_create

nx_secure_tls_session_renegotiate_callback_set

分配将在会话重新协商开始时调用的回调

原型

UINT  nx_secure_tls_ session_renegotiate_callback_set (
                  NX_SECURE_TLS_SESSION *tls_session,
                  ULONG (*func_ptr)(struct NX_SECURE_TLS_SESSION_struct
                  *session));

说明

此服务用于向 TLS 会话分配回调,每当远程主机收到会话重新协商握手的第一条消息时,都会调用此回调。

此回调函数应该作为告知应用程序重新协商握手开始的通知,此应用程序可以选择通过在回调返回任何非零值来终止 TLS 会话,这会导致 TLS 结束 TLS 会话,并返回错误消息。 如果应用程序希望继续重新协商,回调应返回 NX_SUCCESS。

注意

根据 TLS 重协商的语义,无论何时从远程服务器收到 HelloRequest,系统都会为 NetX Secure TLS 客户端调用回调,但在客户端启动重新协商时,则不调用该回调。 在 NetX Secure TLS 服务器上,每当收到重新协商 ClientHello 时(活动 TLS 会话的上下文中收到的 ClientHello),都会调用此回调。 这意味着,无论是远程主机还是本地应用程序发起重新协商,都将调用此回调,因为 TLS 服务器将发送 HelloRequest,远程客户端会响应此请求。

NetX Secure TLS 通过 RFC 5746 实现了安全重新协商标识扩展,可确保重新协商握手不会受到中间人攻击。

参数

  • session_ptr:指向 TLS 会话实例的指针。
  • func_ptr:指向回调函数的指针。

返回值

  • NX_SUCCESS (0x00):成功分配回调。
  • NX_PTR_ERROR (0X07):试图对回调函数或 TLS 会话使用无效指针。

允许来自

线程数

示例

/* Simple callback notifying the user that a renegotiation is starting. */
ULONG tls_renegotiation_callback(NX_SECURE_TLS_SESSION *session)
{
    printf("Renegotiation initiated by remote host\n");

    return(NX_SUCCESS);
}

/* Establish a TLS session with a remote host (TLS Client) */
status =  nx_secure_tls_session_create(&tls_session,
                                       &nx_crypto_tls_ciphers,
                                       crypto_metadata,
                                       sizeof(crypto_metadata));


/* Set callback for renegotiation notification. */
status = nx_secure_tls_session_renegotiate_callback_set(&tls_session,
                                                tls_renegotiation_callback);

另请参阅

  • nx_secure_tls_session_create
  • nx_secure_tls_session_start
  • nx_secure_tls_session_receive
  • nx_secure_tls_session_send
  • nx_secure_tls_session_renegotiate

nx_secure_tls_session_renegotiate

发起与远程主机的会话重新协商握手

原型

UINT  nx_secure_tls_ session_renegotiate (
                  NX_SECURE_TLS_SESSION *tls_session,
                  UINT wait_option);

说明

此服务用于发起与连接的远程 TLS 主机的会话重新协商握手。 重新协商包含之前建立的 TLS 会话上下文中的另一个 TLS 握手。 每个新的握手消息都会使用 TLS 会话进行加密,直到生成新的会话密钥并交换 ChangeCipherSpec 消息,此时将使用新密钥对所有消息进行加密。

建立 TLS 会话之后,即可随时启动重新协商。 如果在 TLS 握手期间或建立 TLS 会话之前尝试重新协商,则不会执行任何操作。

注意

系统调用此服务时将执行整个 TLS 握手,因此完成和返回状态的时间将因当前的 TLS 设置和会话参数而异。

NetX Secure TLS 通过 RFC 5746 实现了安全重新协商标识扩展,可确保重新协商握手不会受到中间人攻击。

参数

  • session_ptr:指向 TLS 会话实例的指针。
  • wait_option:表示服务在返回之前应等待来自远程主机的数据包的时长。 系统会将其传递到 TLS 内的所有 NetX 服务。

返回值

  • NX_SUCCESS (0X00):重新协商成功。
  • NX_NO_PACKET (0x01):未收到任何数据。
  • NX_NOT_CONNECTED (0x38):不再连接底层套接字。
  • NX_SECURE_TLS_HASH_MAC_VERIFY_FAILURE (0x108):收到的消息未通过身份验证哈希检查。
  • NX_SECURE_TLS_UNKNOWN_TLS_VERSION (0x10F):收到的消息在其标头中包含未知的协议版本。
  • NX_SECURE_TLS_ALERT_RECEIVED (0X114):收到来自远程主机的 TLS 警报。
  • NX_SECURE_TLS_RENEGOTIATION_SESSION_INACTIVE (0x134):本地或远程 TLS 会话处于非活动状态,因此无法重新协商。
  • NX_SECURE_TLS_RENEGOTIATION_FAILURE (0x13A):远程主机未提供 SCSV 或安全重新协商扩展,因此无法执行重新协商。
  • NX_PTR_ERROR (0X07):尝试使用的指针无效。
  • NX_SECURE_TLS_SESSION_UNINITIALIZED (0x101):提供的 TLS 会话未初始化。
  • NX_SECURE_TLS_ALLOCATE_PACKET_FAILED (0X111):基础数据包分配失败。

允许来自

线程数

示例

/* Establish a TLS session with a remote host (TLS Client) */
status =  nx_secure_tls_session_create(&tls_session,
                                       &nx_crypto_tls_ciphers,
                                       crypto_metadata,
                                       sizeof(crypto_metadata));


/* Setup a client socket connection.  */
status = nx_tcp_client_socket_connect(&tcp_socket, server_ipv4_address,
REMOTE_SERVER_PORT, NX_WAIT_FOREVER);

/* Start the TLS session. */
status = nx_secure_tls_session_start(&tls_session, &tcp_socket, NX_WAIT_FOREVER);

/* Send some data in the first TLS session. (Check “status” for errors…)*/
status = nx_secure_tls_packet_allocate(&tls_session, &pool_0, &send_packet,
                                       NX_WAIT_FOREVER);
status = nx_packet_data_append(send_packet, "Hello there!\r\n", 14, &pool_0,
                               NX_WAIT_FOREVER);
status = nx_secure_tls_session_send(&tls_session, send_packet,
                                    NX_IP_PERIODIC_RATE);

/* Now renegotiate the session. */
status  = nx_secure_tls_session_renegotiate(&tls_session, NX_WAIT_FOREVER);

/* If status == NX_SUCCESS, new TLS session keys have been generated. */

/* Send some data in the new TLS session. This will be encrypted using the new
   keys. */
status = nx_secure_tls_packet_allocate(&tls_session, &pool_0, &send_packet,
                                       NX_WAIT_FOREVER);
status = nx_packet_data_append(send_packet, "Another message…\r\n", 18, &pool_0,
                               NX_WAIT_FOREVER);
status = nx_secure_tls_session_send(&tls_session, send_packet,
                                    NX_IP_PERIODIC_RATE);

另请参阅

  • nx_secure_tls_session_create
  • nx_secure_tls_session_start
  • nx_secure_tls_session_receive
  • nx_secure_tls_session_send
  • nx_secure_tls_session_renegotiation_callback_set

nx_secure_tls_session_reset

清除并重置 NetX Secure TLS 会话

原型

UINT  nx_secure_tls_session_reset (NX_SECURE_TLS_SESSION *session_ptr);

说明

此服务用于清除 TLS 会话,并将状态重置为刚创建会话的状态,以便在新会话中重复使用现有的 TLS 会话对象。

参数

  • session_ptr:指向 TLS 会话实例的指针。

返回值

  • NX_SUCCESS (0X00):成功初始化 TLS 会话。
  • NX_INVALID_PARAMETERS (0x4D):TLS 会话指针无效。
  • NX_PTR_ERROR (0X07):尝试使用的指针无效。

允许来自

线程数

示例

/* Reset a TLS session.  */
status =  nx_secure_tls_session_reset(&tls_session);


/* If status is NX_SUCCESS the session was successfully reset and may be reused.*/

另请参阅

  • nx_secure_x509_certificate_initialize
  • nx_secure_tls_remote_certificate_allocate
  • nx_secure_tls_session_start
  • nx_secure_tls_session_delete
  • nx_secure_tls_session_send
  • nx_secure_tls_session_receive
  • nx_secure_tls_session_create

nx_secure_tls_session_send

通过 NetX Secure TLS 会话发送数据

原型

UINT  nx_secure_tls_session_send(NX_SECURE_TLS_SESSION *session_ptr,
                                    NX_PACKET *packet_ptr,
                                    ULONG wait_option);

说明

此服务使用指定的活动 TLS 会话发送提供的 NX_PACKET 中的数据,并在将其发送到远程主机之前处理该数据的加密。 如果接收方最近一次播发的窗口大小低于此请求,则此服务可以根据指定的等待选项挂起。

重要

除非返回了错误,否则应用程序不应在此调用后释放该数据包。 这样做会导致不可预知的结果,因为网络驱动程序会在传输后释放该数据包。

参数

  • session_ptr:指向 TLS 会话实例的指针。
  • packet_ptr:指向包含要发送的数据的 TLS 数据包的指针。
  • wait_option:定义当请求大于接收方窗口大小时此服务的行为方式。

返回值

  • NX_SUCCESS (0X00):成功初始化 TLS 会话。
  • NX_NO_PACKET (0x01):未收到任何数据。
  • NX_NOT_CONNECTED (0x38):不再连接底层套接字。
  • NX_SECURE_TLS_TCP_SEND_FAILED (0x109):基础 TCP 套接字发送失败。
  • NX_PTR_ERROR (0X07):尝试使用的指针无效。
  • NX_SECURE_TLS_SESSION_UNINITIALIZED (0x101):提供的 TLS 会话未初始化。

允许来自

线程数

示例

/* Send a packet using an active TLS session previously created and started with
nx_secure_tls_session_start. Wait until a packet is sent, blocking otherwise.   */
status =  nx_secure_tls_session_send(&tls_session, &packet_ptr, NX_WAIT_FOREVER);


/* If status is NX_SUCCESS the packet has been sent. */

另请参阅

  • nx_tcp_socket_receive
  • nx_secure_x509_certificate_initialize
  • nx_secure_tls_remote_certificate_allocate
  • nx_secure_tls_packet_allocate
  • nx_secure_tls_session_start
  • nx_secure_tls_session_delete
  • nx_secure_tls_session_receive
  • nx_secure_tls_session_end
  • nx_secure_tls_session_create

nx_secure_tls_session_server_callback_set

为 TLS 设置在 TLS 服务器握手开始时调用的回调

原型

UINT  nx_secure_tls_ session_server_callback_set (
                 NX_SECURE_TLS_SESSION *tls_session,
                 ULONG (*func_ptr)(NX_SECURE_TLS_SESSION *tls_session,
                                   NX_SECURE_TLS_HELLO_EXTENSION
                                   *extensions, UINT num_extensions));

说明

此服务将函数指针分配给 TLS 会话,当 TLS 服务器握手收到 ClientHello 消息时,TLS 将调用该会话。 使用此回调函数,应用程序可以处理收到的 ClientHello 消息中需要输入或决策的任何 TLS 扩展。

系统通过调用 TLS 会话控制块和 NX_SECURE_TLS_HELLO_EXTENSION 对象的数组来执行此回调。 扩展对象的数组应该传递到一个帮助程序函数,该函数将查找并分析特定扩展。 有关分析 hello 消息中提供的 TLS 扩展的示例帮助程序函数,请参阅 nx_secure_tls_session_sni_extension_parse。

服务器回调还可用于通过 nx_secure_tls_active_certificate_set 为 TLS 服务器选择活动标识证书。 这种情况通常在响应服务器名称指示 (SNI) 的扩展时发生,TLS 客户端可通过此扩展指示它正在尝试联系的服务器。 有关更多详细信息,请参阅 nx_secure_tls_session_sni_extension_parse 和 nx_secure_tls_active_certificate_set 的引用。

参数

  • session_ptr:指向之前创建的 TLS 会话实例的指针。
  • func_ptr:指向 TLS 服务器回调函数的指针。

返回值

  • NX_SUCCESS (0X00):成功分配函数指针。
  • NX_PTR_ERROR (0X07):TLS 会话指针无效。

允许来自

线程数

示例

/* Application-supplied function to map server DNS name to a specific certificate
   ID. The certificate ID is supplied by the application when the certificate is
   added with nx_secure_tls_server_certificate_add. */
UINT application_find_id_by_dns_name(NX_SECURE_X509_DNS_NAME *dns_name)
{
    if(strncmp(dns_name->nx_secure_x509_dns_name, “server_name”,
               dns_name->nx_secure_x509_dns_name_length) == 0)
    {
        /* DNS name matches one we know, return it’s ID. */
        return(0x12);
    }

    /* Unknown DNS name, return 0 to indicate no matching ID found. */
    return(0);
}

/* Callback routine used to process ClientHello extensions and perform other
   runtime actions at the beginning of a TLS handshake (such as selecting an
   identify certificate to provide to the client). */
ULONG tls_server_callback(NX_SECURE_TLS_SESSION *session,
                          NX_SECURE_TLS_HELLO_EXTENSION *extensions, UINT
                          num_extensions)
{
UINT status;
NX_SECURE_X509_DNS_NAME dns_name;
UINT cert_id;
NX_SECURE_X509_CERT *certificate;


    /* Find and parse a Server Name Indication (SNI) extension. */
    status = nx_secure_tls_session_sni_extension_parse(session, extensions,
                                                       num_extensions, &dns_name);

    if(status != NX_SUCCESS && status != NX_SECURE_TLS_EXTENSION_NOT_FOUND)
    {
        /* Parsed an invalid extension, return the error. */
        return(status);
    }

    if(status == NX_SECURE_TLS_EXTENSION_NOT_FOUND)
    {
            /* SNI extension not found, just return success to use the default
               certificate. */
            return(NX_SUCCESS);
    }

    /* Find the application-supplied numeric identifier for the specified DNS
       name provided by the remote client. */
    cert_id = application_find_id_by_dns_name(&dns_name);

    /* If cert_id is 0, just use the default identity certificate added with
       nx_secure_tls_local_certificate_add. */
    if(cert_id != 0)
    {
        /* Application found a matching name, find the certificate in our
           store. */
        status = nx_secure_tls_server_certificate_find(tls_session, &certificate,
                                                       cert_id);

        if(status != NX_SUCCESS)
        {
            /* Didn’t find a valid certificate with the supplied ID. Return an
               error so TLS can shut down the handshake. */
            return(NX_SECURE_TLS_CERTIFICATE_NOT_FOUND);
        }

        /* Set the active identity certificate – the certificate should have been
           added to the local store at application start with
           nx_secure_tls_local_certificate_add. */
        nx_secure_tls_active_certificate_set(session, certificate);
    }

    return(NX_SUCCESS);
}

/* TLS setup routine. */
UINT tls_setup(NX_SECURE_TLS_SESSION *tls_session)
{
        /* Add callback to TLS session.  */
        status =  nx_secure_tls_session_server_callback_set(tls_session,
                                                            server_callback);

        /* If status is NX_SUCCESS the callback was added and will be invoked
           immediately after a ClientHello message is received. */

        return(status);
}

另请参阅

  • nx_secure_tls_session_create
  • nx_secure_tls_session_client_callback_set
  • nx_secure_tls_active_certificate_set
  • nx_secure_tls_session_sni_extension_parse
  • nx_secure_tls_server_certificate_add
  • nx_secure_tls_server_certificate_find

nx_secure_tls_session_sni_extension_parse

分析从 TLS 客户端接收到的服务器名称指示 (SNI) 扩展

原型

UINT  nx_secure_tls_session_sni_extension_parse(
                                    NX_SECURE_TLS_SESSION *session_ptr,
                                    NX_SECURE_TLS_HELLO_EXTENSION
                                    *extensions,
                                    UINT num_extensions,
                                    NX_SECURE_X509_DNS_NAME *dns_name);

说明

此服务应该从 TLS 服务器会话回调中调用,并使用 nx_secure_tls_session_server_callback_set 添加到 TLS 会话中。 从远程 TLS 客户端收到 ClientHello 消息后,系统将调用该回调,并为该回调提供一个可用扩展数组(以及该数组中的扩展数)。 可将该数组及其长度直接传递到此例程,以确定是否存在 SNI 扩展,如果不存在,则返回 NX_SECURE_TLS_EXTENSION_NOT_FOUND,这只表示客户端选择不提供 SNI 扩展(这不是错误)。

如果找到了 SNI 扩展,系统会在 dns_name 结构中返回 TLS 客户端提供的 X.509 DNS 名称。 目前,SNI 扩展仅提供单个 DNS 名称条目,TLS 服务器可能会使用该条目来确定要发送到远程客户端的标识证书。**

NX_SECURE_X509_DNS_NAME 结构只是将 DNS 名称作为 UCHAR 字符串包含在 nx_secure_x509_dns_name 字段中,将名称字符串的长度包含在 nx_secure_x509_dns_name_length 中。 宏 NX_SECURE_X509_DNS_NAME_MAX 用于控制 nx_secure_x509_dns_name 缓冲区的大小。

参数

  • session_ptr:指向 TLS 会话实例的指针。
  • extensions:指向 TLS Hello 扩展数组(来自会话回调)的指针。
  • num_extensions:来自会话回调的数组中的扩展数量。
  • dns_name:返回 SNI 扩展中提供的 DNS 名称。

返回值

  • NX_SUCCESS (0X00):成功分析扩展。
  • NX_PTR_ERROR (0x07):扩展数组或 TLS 会话指针无效。
  • 找不到 NX_SECURE_TLS_EXTENSION_NOT_FOUND (0X136) SNI 扩展。
  • NX_SECURE_TLS_SNI_EXTENSION_INVALID (0X137) SNI 扩展格式无效。

允许来自

线程数

示例

另请参阅

  • nx_secure_tls_session_server_callback_set
  • nx_secure_tls_session_client_callback_set
  • nx_secure_tls_server_callback_set
  • nx_secure_tls_active_certificate_set

nx_secure_tls_session_sni_extension_set

设置要发送到远程服务器的服务器名称指示 (SNI) 扩展 DNS 名称

原型

UINT  nx_secure_tls_session_sni_extension_set(
                                    NX_SECURE_TLS_SESSION *session_ptr,
                                    NX_SECURE_X509_DNS_NAME *dns_name);

说明

使用此服务,TLS 客户端应用程序可以使用服务器名称指示 (SNI) TLS 扩展向远程 TLS 服务器提供首选服务器 DNS 名称。 使用 SNI 扩展,服务器可以根据客户端指示的服务器首选项来选择合适的标识证书和参数。 SNI 扩展目前只支持发送单个 DNS 名称,因此使用单数形式的名称参数。 dns_name 参数必须使用 nx_secure_x509_dns_name_initialize 进行初始化,并且将包含客户端的首选服务器。 若要取消设置扩展名称,只需使用 NX_NULL 的“dns_name”参数值调用此服务。

NX_SECURE_X509_DNS_NAME 结构只是将 DNS 名称作为 UCHAR 字符串包含在 nx_secure_x509_dns_name 字段中,将名称字符串的长度包含在 nx_secure_x509_dns_name_length 中。 宏 NX_SECURE_X509_DNS_NAME_MAX 用于控制 nx_secure_x509_dns_name 缓冲区的大小。

注意

必须先调用此例程,然后再调用 nx_secure_tls_session_start,否则 ClientHello 将不包含 SNI 扩展。

参数

  • session_ptr:指向 TLS 会话实例的指针。
  • dns_name:应用程序提供的 DNS 名称。

返回值

  • NX_SUCCESS (0X00):成功添加 DNS 服务器名称。
  • NX_PTR_ERROR (0X07):DNS 名称或 TLS 会话指针无效。

允许来自

线程数

示例

#define TLS_SNI_SERVER_NAME “www.example.com”

NX_SECURE_X509_DNS_NAME dns_name;
NX_SECURE_TLS_SESSION client_tls_session;

/* Application where TLS session is started. */
void main()
{
    /* Create a TLS session for our socket. Ciphers and metadata defined
       elsewhere. See nx_secure_tls_session_create reference for more
       information. */
    status =  nx_secure_tls_session_create(&client_tls_session,
                                           &nx_crypto_tls_ciphers,
                                           server_crypto_metadata,
                                           sizeof(server_crypto_metadata));


    /* Initialize the DNS server name we want to send in the SNI extension. */
    nx_secure_x509_dns_name_initialize(&dns_name, TLS_SNI_SERVER_NAME,
                                    strlen(TLS_SNI_SERVER_NAME));

    /* The SNI server name needs to be set prior to starting the TLS session. */
    nx_secure_tls_session_sni_extension_set(&tls_session, &dns_name);

   /* Start TLS session as normal. */
}

另请参阅

  • nx_secure_tls_session_start
  • nx_secure_x509_dns_name_initialize

nx_secure_tls_session_start

启动 NetX Secure TLS 会话

原型

UINT  nx_secure_tls_session_start(NX_SECURE_TLS_SESSION *session_ptr,
                                  NX_TCP_SOCKET *tcp_socket_ptr,
                                  ULONG wait_option);

说明

此服务使用提供的 TLS 会话控制块和连接的 TCP 套接字启动 TLS 会话。 成功调用 nx_tcp_client_socket_connect 或 nx_tcp_server_socket_accept 之后,必须已完成 TCP 连接。

此服务将根据 TCP 套接字确定 TLS 会话的类型(客户端或服务器)。

等待选项定义了此服务在 TLS 握手期间的行为方式。

参数

  • session_ptr:指向 TLS 会话实例的指针。
  • tcp_socket_ptr:指向已连接的 TCP 套接字的指针。
  • wait_option:定义了此服务在 TLS 握手期间的行为方式。

返回值

  • NX_SUCCESS (0X00):成功初始化 TLS 会话。
  • NX_NOT_CONNECTED (0x38):不再连接底层套接字。
  • NX_SECURE_TLS_UNRECOGNIZED_MESSAGE_TYPE (0x102):收到的 TLS 消息类型不正确。
  • NX_SECURE_TLS_UNSUPPORTED_CIPHER (0x106):不支持远程主机提供的密码。
  • NX_SECURE_TLS_HANDSHAKE_FAILURE (0X107):TLS 握手期间的消息处理失败。
  • NX_SECURE_TLS_HASH_MAC_VERIFY_FAILURE (0x108):传入消息未通过哈希 MAC 检查。
  • NX_SECURE_TLS_TCP_SEND_FAILED (0x109):基础 TCP 套接字发送失败。
  • NX_SECURE_TLS_INCORRECT_MESSAGE_LENGTH (0x10A):传入消息的长度字段无效。
  • NX_SECURE_TLS_BAD_CIPHERSPEC (0x10B):传入的 ChangeCipherSpec 消息不正确。
  • NX_SECURE_TLS_INVALID_SERVER_CERT (0x10C):传入 TLS 证书无法用于识别远程 TLS 服务器。
  • NX_SECURE_TLS_UNSUPPORTED_PUBLIC_CIPHER (0x10D):远程主机提供的公钥密码不受支持。
  • NX_SECURE_TLS_NO_SUPPORTED_CIPHERS (0x10E):远程主机指出 NetX Secure TLS 堆栈不支持任何密码套件。
  • NX_SECURE_TLS_UNKNOWN_TLS_VERSION (0x10F):收到的 TLS 消息在其标头中包含未知的 TLS 版本。
  • NX_SECURE_TLS_UNSUPPORTED_TLS_VERSION (0x110):收到的 TLS 消息在其标头中有已知但不受支持的 TLS 版本。
  • NX_SECURE_TLS_ALLOCATE_PACKET_FAILED (0X111):内部 TLS 数据包分配失败。
  • NX_SECURE_TLS_INVALID_CERTIFICATE (0x112):远程主机提供的证书无效。
  • NX_SECURE_TLS_ALERT_RECEIVED (0x114):远程主机发送了警报,指示出现错误并结束了 TLS 会话。
  • NX_SECURE_TLS_MISSING_CRYPTO_ROUTINE (0x13B):密码套件表中的条目具有 NULL 函数指针。
  • NX_SECURE_TLS_INAPPROPRIATE_FALLBACK (0x146):远程 TLS ClientHello 包含回退 SCSV,并且尝试了版本回退。
  • NX_PTR_ERROR (0X07):尝试使用的指针无效。

允许来自

线程数

示例

NX_TCP_SOCKET tcp_socket;
NX_SECURE_TLS_SESSION tls_session;
NX_SECURE_X509_CERT certificate;

/* Initialize the TLS session structure. */
nx_secure_tls_session_create(&tls_session,
                              &nx_crypto_tls_ciphers,
                              crypto_metadata,
                              sizeof(crypto_metadata));

/* Setup the TLS packet reassembly buffer. */
status = nx_secure_tls_session_packet_buffer_set(&tls_session, tls_packet_buffer,
                                                 sizeof(tls_packet_buffer));

/* Initialize a certificate for the TLS server. */
status =  nx_secure_x509_certificate_initialize(&certificate, certificate_data, 500,
NX_NULL, 0, private_key, 64);

/* If status is NX_SUCCESS, certificate is initialized. */

/* Add the certificate a local certificate to identify this TLS server. */
status = nx_secure_tls_add_local_certificate(&tls_session, &certificate);

/* If status is NX_SUCCESS, certificate was added successfully. */

/* Create and start a TCP socket as a server. */
/* NOTE: This assumes an IP instance called “ip_0” has already been created. */

/* Create a TCP server socket on the previously created IP instance, with normal
   delivery, IP fragmentation enabled, default time to live, a 8192-byte receive
   window, no urgent callback routine, and the "client_disconnect" routine to
   handle disconnection initiated from the other end of the connection.  */
status =  nx_tcp_socket_create(&ip_0, &tcp_socket, "TLS Server Socket", NX_IP_NORMAL,
                               NX_FRAGMENT_OKAY, NX_IP_TIME_TO_LIVE, 8192, NX_NULL,
                               NX_NULL);

/* If status is NX_SUCCESS, the TCP socket was created successfully. */

/* Start up a TCP server socket by listening on port 443 with a listen queue of
   size 5. */
status =  nx_tcp_server_socket_listen(&ip_0, 443, &tcp_socket, 5, NX_NULL);

/* Application main loop. */
while(1)
{
        /* Accept incoming requests on the TCP socket. */
        status =  nx_tcp_server_socket_accept(&tcp_socket, NX_WAIT_FOREVER);

        /* At this point, the TCP socket should be established (but not the TLS
        session yet). */

        /* Start the TLS session on our active TCP socket. */
        status = nx_secure_tls_session_start(&tls_session, &tcp_socket,
                                             NX_WAIT_FOREVER);

        /* At this point, if status is NX_SUCCESS, the TLS session has been
           established.  Application may now send/receive data through this
           channel. */

        /* Send and receive data using the TLS session. */
        /* Allocate TLS packets using nx_secure_tls_packet_allocate, write data with
           nx_packet_data_append, read data with nx_packet_data_extract_offset. */

        /* Send TLS data. */
        nx_secure_tls_session_send(&tls_session, &send_packet, NX_WAIT_FOREVER);

        nx_secure_tls_session_receive(&tls_session, &receive_packet_ptr,
        NX_WAIT_FOREVER);


        /* Once all application data is sent/received, end the TLS session. */
        status = nx_secure_tls_session_end(&tls_session);

        /* If status is NX_SUCCESS, the TLS session has been closed properly. */

        /* Now disconnect the TCP server socket from the client.  */
        nx_tcp_socket_disconnect(&tcp_socket, 200);

        /* Unaccept the TCP server socket.  Note that unaccept is called even if
           disconnect or accept fails.  */
        nx_tcp_server_socket_unaccept(&tcp_socket);

        /* Setup server socket for listening with this socket again.  */
        nx_tcp_server_socket_relisten(&ip_0, 443, &tcp_socket);
}

/* When the server application is shut down, clean up the TLS session. */
nx_secure_tls_session_delete(&tls_session);

/* Finally, clean up the TCP socket as well. */
nx_tcp_socket_delete(&tcp_socket);

另请参阅

  • nx_tcp_socket_receive
  • nx_secure_x509_certificate_initialize
  • nx_secure_tls_remote_certificate_allocate
  • nx_secure_tls_session_send
  • nx_secure_tls_session_delete
  • nx_secure_tls_session_receive
  • nx_secure_tls_packet_allocate
  • nx_secure_tls_session_end
  • nx_secure_tls_session_create
  • nx_tcp_socket_accept
  • nx_tcp_socket_listen
  • nx_tcp_socket_disconnect
  • nx_tcp_socket_unaccept
  • nx_tcp_socket_relisten
  • nx_tcp_socket_delete
  • nx_packet_allocate
  • nx_packet_data_append
  • nx_packet_data_extract_offset

nx_secure_tls_session_time_function_set

为 NetX Secure TLS 会话分配时间戳函数

原型

UINT  nx_secure_tls_time_function_set(
                              NX_SECURE_TLS_SESSION *session_ptr,
                              ULONG (*time_func_ptr)(void));

说明

此函数设置一个函数指针,TLS 在需要获取当前时间时将调用该函数指针,这种方法在各种 TLS 握手消息和证书验证中使用。

根据 TLS RFC 5246 中的 ClientHello 要求,此函数应以 UNIX 32 位格式返回当前 GMT(自 UTC 1970 年 1 月 1 日午夜开始的秒数,忽略闰秒)。

如果未分配时间戳函数,将使用 TLS 握手中的时间戳值 0,证书过期检查将不起作用。

参数

  • session_ptr:指向 TLS 会话实例的指针。
  • time_func_ptr:指向以 UNIX 32 位格式返回当前时间 (GMT) 的函数的指针。

返回值

  • NX_SUCCESS (0X00):成功初始化 TLS 会话。
  • NX_INVALID_PARAMETERS (0x4D):TLS 会话指针无效。
  • NX_PTR_ERROR (0X07):尝试使用的指针无效。

允许来自

线程数

示例

/* This function returns a 32-bit UNIX-style representation of the current GMT
   time. */
ULONG get_gmt_time(void)
{
ULONG time_value;

   /* Platform-specific time calculation goes here… */

   return(time_value);
}

/* Reset a TLS session.  */
status =  nx_secure_tls_timestamp_function_set(&tls_session, get_gmt_time);


/* If status is NX_SUCCESS the function was successfully added.*/

另请参阅

  • nx_secure_x509_certificate_initialize
  • nx_secure_tls_remote_certificate_allocate
  • nx_secure_tls_session_start
  • nx_secure_tls_session_delete
  • nx_secure_tls_session_sendnx_secure_tls_session_receive
  • nx_secure_tls_session_create

nx_secure_tls_trusted_certificate_add

将受信任的证书添加到 NetX Secure TLS 会话

原型

UINT  nx_secure_tls_trusted_certificate_add(NX_SECURE_TLS_SESSION
                            *session_ptr, NX_SECURE_X509_CERT *certificate_ptr);

说明

此服务用于将已初始化的 NX_SECURE_X509_CERT 结构实例添加到 TLS 会话。 TLS 堆栈使用此证书来验证远程主机在 TLS 握手期间提供的证书。

TLS 客户端模式需要使用受信任的证书。

只有启用客户端证书身份验证,TLS 服务器模式才需要使用受信任的证书。

参数

  • session_ptr:指向之前创建的 TLS 会话实例的指针。
  • certificate_ptr:指向已初始化的 TLS 证书实例的指针。

返回值

  • NX_SUCCESS (0X00):成功添加证书。
  • NX_INVALID_PARAMETERS (0X4D):尝试添加的证书无效。
  • NX_PTR_ERROR (0X07):TLS 会话指针无效。

允许来自

线程数

示例

/* Initialize certificate structure. */
status = nx_secure_x509_certificate_initialize(&certificate, certificate_data,
                                               certificate_buffer,
                                               sizeof(certificate_buffer), 500,
                                               private_key, 64);

/* Add certificate to TLS session.  */
status =  nx_secure_tls_trusted_certificate_add(&tls_session, &certificate);


/* If status is NX_SUCCESS the certificate was successfully added.  */

另请参阅

  • nx_secure_x509_certificate_initialize
  • nx_secure_tls_session_create
  • nx_secure_tls_remote_certificate_allocate
  • nx_secure_tls_trusted_certificate_remove

nx_secure_tls_trusted_certificate_remove

从 NetX Secure TLS 会话中删除受信任的证书

原型

UINT  nx_secure_tls_trusted_certificate_remove(
                                    NX_SECURE_TLS_SESSION *session_ptr,
                                    UCHAR *common_name,
                                    UINT common_name_length);

说明

此服务从 TLS 会话中删除受信任的证书,并将其键入证书中的“Common Name”字段。

参数

  • session_ptr:指向之前创建的 TLS 会话实例的指针。
  • common_name:要删除的证书的公用名值。
  • common_name_length:公用名字符串的长度。

返回值

  • NX_SUCCESS (0X00):成功添加证书。
  • NX_PTR_ERROR (0X07):TLS 会话指针无效。
  • NX_SECURE_TLS_CERTIFICATE_NOT_FOUND (0X119):找不到证书。

允许来自

线程数

示例

/* Remove certificate from TLS session.  */
status =  nx_secure_tls_trusted_certificate_remove(&tls_session,
                                                “www.example.com”, 15);


/* If status is NX_SUCCESS the certificate was successfully removed.  */

另请参阅

  • nx_secure_x509_certificate_initialize
  • nx_secure_tls_session_create
  • nx_secure_tls_remote_certificate_allocate
  • nx_secure_tls_trusted_certificate_add

nx_secure_x509_certificate_initialize

为 NetX Secure TLS 初始化 X.509 证书

原型

UINT  nx_secure_x509_certificate_initialize(
                  NX_SECURE_X509_CERT *certificate_ptr,
                  const UCHAR *certificate_data,
                  USHORT certificate_data_length,
                  UCHAR *raw_data_buffer,
                  USHORT buffer_size,
                  const UCHAR *private_key_data,
                  USHORT private_key_data_length,
                  UINT private_key_type);

说明

此服务用于初始化采用二进制编码的 X.509 数字证书中的 NX_SECURE_X509_CERT 结构,以便在 TLS 会话中使用。

证书数据必须是采用 DER 编码的二进制格式的有效 X.509 数字证书。 只要提供了指向该数据的 UCHAR 指针,就可以从任何源(例如文件系统、编译的常量缓冲区等)获取数据。

raw_data_buffer 参数及其大小是可选参数,用于指定在分析之前要将证书数据复制到其中的专用缓冲区。 如果将 raw_data_buffer 作为 NX_NULL 传递,NX_SECURE_X509_CERT 结构将直接指向 certificate_data 数组(在此例中已忽略 buffer_size)。 如果将 raw_data_buffer 作为 NX_NULL 传递,请不要修改 certificate_data 指针指向的数据,否则证书处理可能会失败!

私钥参数适用于本地标识证书,服务器使用私钥来解密来自客户端的传入密钥数据(已使用服务器的公钥加密),客户端使用私钥在服务器请求客户端证书时向服务器验证其身份。 使用此 API 添加私钥会自动将关联的证书标记为 TLS 应用程序的标识证书。 当出于其他目的(例如,受信任的存储)初始化证书时,应将 private_key_data 参数作为 NULL 传递,将 private_key_data_length 作为 0 传递,并将 private_key_type 作为 NX_SECURE_X509_KEY_TYPE_NONE 传递。

private_key_type 参数表示私钥的格式设置。 例如,如果私钥是采用 DER 编码的 PKCS#1 格式的 RSA 私钥,则应将 private_key_type 作为 NX_SECURE_X509_KEY_TYPE_RSA_PKCS1_DER 传递,这是 NetX Secure 已知的类型,系统将立即对其进行分析并保存,以供以后使用。

private_key_type 还支持用户定义的密钥类型23,这些类型适用于具有特定密钥格式或其他需求的平台和应用程序。 例如,基于硬件的加密引擎可能使用 NetX Secure 软件无法理解的特定格式,或者私钥可能已加密或用加密令牌表示,使用受信任的平台模块 (TPM) 或 PKCS#11 加密硬件时可能会出现这种情况。 使用用户定义的密钥类型时,系统会将密钥数据逐字传递到适当的加密例程,例如,在不进行任何分析或处理的情况下,将 RSA 私钥直接传递到密码套件表中提供给 TLS 的 RSA 加密例程。 还会将用户定义的密钥类型传递到加密例程(在使用 RSA 的情况下,这是“op”参数)。

用户定义的密钥的范围涵盖 32 位无符号整数的上半部分,从 0x0001 0000 到 0xFFFF FFFF。 小于 0x0001 0000 的值预留给 NetX Secure 使用。

用户定义的密钥类型是一项高级功能,需要使用自定义加密例程来处理原始私钥数据。 如果需要此功能,请联系你的 Express Logic 代表。

参数

  • certificate_ptr:指向已初始化的 X.509 证书实例的指针。
  • certificate_data:指向采用 DER 编码的 X.509 二进制数据的指针。
  • raw_data_buffer:指向可选专用证书数据缓冲区的指针。
  • buffer_size:可选专用证书数据缓冲区的大小。
  • certificate_data_length:证书二进制数据的长度(以字节为单位)。
  • private_key_data:指向可选私钥数据的指针。
  • private_key_data_length:私钥数据的长度。
  • private_key_type:密钥类型标识符。

返回值

  • NX_SUCCESS (0X00):成功添加证书。
  • NX_PTR_ERROR (0X07):尝试使用的指针无效。
  • NX_SECURE_TLS_INVALID_CERTIFICATE (0X112):证书数据不包含使用 DER 编码的 X.509 证书。
  • NX_SECURE_TLS_UNSUPPORTED_PUBLIC_CIPHER (0X10D):证书没有 NetX Secure 支持的公钥密码。
  • NX_SECURE_X509_INVALID_CERTIFICATE_SEQUENCE (0X186):私钥或证书不包含有效的 ASN.1 序列。
  • NX_SECURE_PKCS1_INVALID_PRIVATE_KEY (0x18A):提供的私钥不是有效的 PKCS#1 RSA 密钥。
  • NX_SECURE_X509_INVALID_PRIVATE_KEY_TYPE (0x19D):提供的私钥类型不是用户定义的,并且与任何已知类型都不匹配。

允许来自

线程数

示例

/* Initialize certificate structure. The certificate structure will point directly
   into the certificate_data array since we are passing the raw_data_buffer as
   NX_NULL. This certificate has a private key so it will be used to identify this
   device. */
status =  nx_secure_x509_certificate_initialize(&certificate, certificate_data,
500, NX_NULL, 0, private_key, 64, NX_SECURE_X509_KEY_TYPE_RSA_PKCS1_DER);


/* If status is NX_SUCCESS the certificate was successfully initialized.  */

另请参阅

  • nx_secure_local_certificate_add
  • nx_secure_tls_session_create
  • nx_secure_tls_remote_certificate_allocate
  • 将 X.509 证书导入第 3 章中的“NetX Secure”。

nx_secure_x509_common_name_dns_check

根据 X.509 证书检查 DNS 名称

原型

UINT  nx_secure_x509_common_name_dns_check(
                        NX_SECURE_X509_CERT *certificate,
                        const UCHAR *dns_tld, UINT dns_tld_length);

说明

此服务根据调用方提供的顶级域名 (TLD) 检查证书的公用名,以便执行远程主机的 DNS 验证。 此实用程序函数应该从应用程序提供的证书验证回调例程中调用。 TLD 名称应该是用于访问远程主机的 URL 的顶部部分(在第一个斜杠之前用“.”分隔的字符串)。 如果公用名包含通配符(如 example.com),则通配符将匹配所有具有相同后缀的项。请注意,只有第一个通配符(“ ”)出现时(从右到左读取),才会考虑通配符匹配项,例如,abc.*.example.com 将匹配所有以“example.com”结尾的名称。

如果公用名与提供的字符串不匹配,系统会分析“subjectAltName”扩展(如果此名称在证书存在),还会比较任何 DNSName 条目。 如果这些条目都不匹配,则会返回错误。

务必要了解预期证书中公用名(和 subjectAltName 条目)的格式。 例如,某些证书可能使用原始 IP 地址或通配符。 必须为 DNS TLD 字符串设置格式,使其与接收的证书中的预期值匹配。

参数

  • certificate_ptr:指向 X.509 证书实例的指针。
  • dns_tld:要比较的顶级域名。
  • dns_tld_length:TLD 字符串的长度。

返回值

  • NX_SUCCESS (0x00):成功与公用名或 subjectAltName 进行比较。
  • NX_SECURE_X509_CERTIFICATE_DNS_MISMATCH (0x195):找不到匹配的名称。
  • NX_PTR_ERROR (0X07):尝试使用的指针无效。

允许来自

线程数

示例

/* Callback routine used to perform additional checks on a certificate. */
ULONG certificate_callback(NX_SECURE_TLS_SESSION *session, NX_SECURE_X509_CERT
*certificate)
{
ULONG status;
UCHAR *tld = “www.example.com”;

    /* Check our DNS TLD against the certificate provided by the
       remote TLS host. */
    status = nx_secure_x509_common_name_dns_check(certificate, tld, strlen(tld));

        if(status != NX_SUCCESS)
        {
            /* TLD did not match any names in the certificate. */
            return(status);
        }

        /* DNS validation and any other checks were successful. */
        return(NX_SUCCESS);
}

…

/* Add callback to TLS session in TLS setup routine.  */
status =  nx_secure_tls_session_certificate_callback_set(&tls_session,
                                                         certificate_callback);

另请参阅

  • nx_secure_tls_session_create
  • nx_secure_tls_session_certificate_callback_set
  • nx_secure_x509_crl_revocation_check

nx_secure_x509_crl_revocation_check

根据提供的证书吊销列表 (CRL) 检查 X.509 证书

原型

UINT  nx_secure_x509_crl_revocation_check(const UCHAR *crl_data,
                              UINT crl_length,
                              NX_SECURE_X509_CERTIFICATE_STORE *store,
                              NX_SECURE_X509_CERT *certificate);

说明

此服务使用采用 DER 编码的证书吊销列表,并在该列表中搜索特定的证书。 系统根据提供的证书存储来验证 CRL 的颁发者,验证 CRL 颁发者是否与要检查的证书相同,并使用相关证书的序列号搜索已吊销的证书列表。 如果颁发者匹配,签名已签出,并且证书不在列表中,则表示调用成功。 所有其他情况都会导致返回错误。

参数

  • crl_data:指向使用 DER 编码的 CRL 的指针。
  • crl_length:CRL 数据的长度(以字节为单位)。
  • store:指向 X.509 证书存储区的指针。
  • certificate_ptr:指向 X.509 证书实例的指针。

返回值

  • NX_SUCCESS (0X00):成功验证了证书未被吊销。
  • NX_SECURE_TLS_CERTIFICATE_NOT_FOUND (0X119):找不到 CRL 颁发者证书。
  • NX_SECURE_TLS_ISSUER_CERTIFICATE_NOT_FOUND (0X11B):找不到证书颁发者证书。
  • NX_SECURE_X509_ASN1_LENGTH_TOO_LONG (0x182):CRL ASN.1 包含无效的长度字段。
  • NX_SECURE_X509_UNEXPECTED_ASN1_TAG (0x189) :CRL 包含无效的 ASN. 1。
  • NX_SECURE_X509_CHAIN_VERIFY_FAILURE (0x18C):证书链验证失败。
  • NX_SECURE_X509_CRL_ISSUER_MISMATCH (0X197):CRL 和证书颁发者不匹配。
  • NX_SECURE_X509_CRL_SIGNATURE_CHECK_FAILED (0X198):CRL 签名无效。
  • NX_SECURE_X509_CRL_CERTIFICATE_REVOKED (0x199):在 CRL 中找到了要检查的证书,因此将吊销该证书。
  • NX_PTR_ERROR (0X07):尝试使用的指针无效。

允许来自

线程数

示例

/* CRL obtained for the expected certificate issuer through some means (downloaded
   from server manually, obtained from CRL endpoint, etc…) */
const UCHAR *crl_data;
UINT crl_length = 300;

/* Callback routine used to perform additional checks on a certificate. */
ULONG certificate_callback(NX_SECURE_TLS_SESSION *session, NX_SECURE_X509_CERT
*certificate)
{
ULONG status;
NX_SECURE_X509_CERTIFICATE_STORE *store;

    /* Obtain a certificate store to check against. In the certificate callback,
       it usually makes the most sense to use the store associated with the TLS
       session. */
    store = &session -> nx_secure_tls_credentials.nx_secure_tls_certificate_store;

    /* Check our certificate against the CRL and TLS certificate store. */
    status = nx_secure_x509_crl_revocation_check(crl, crl_length, store,
                                                 certificate);

        if(status != NX_SUCCESS)
        {
            if(status == NX_SECURE_X509_CRL_CERTIFICATE_REVOKED)
            {
                /* Certificate was revoked. */
               return(status);
            }
            else
            {
               /* CRL was invalid or some other issue. In this case the certificate
                  may still be valid since the CRL itself was a problem. At this
                  point it is up to the application to decide whether to continue
                  with the TLS handshake. For this example, assume certificate is
                  valid (faulty CRL is a possible Denial-of-Service attack).*/
               status = NX_SUCCESS;
        }

    /* Other certificate checking can go here. */

    /* Return status of certificate checks. */
    return(status);
}

…

/* Add callback to TLS session in TLS setup routine.  */
status =  nx_secure_tls_session_certificate_callback_set(&tls_session,
                                                         certificate_callback);

另请参阅

  • nx_secure_tls_session_create
  • nx_secure_tls_session_certificate_callback_set
  • nx_secure_x509_common_name_dns_check

nx_secure_x509_dns_name_initialize

初始化 X.509 DNS 名称结构

原型

UINT  nx_secure_x509_dns_name_initialize(
                        NX_SECURE_X509_DNS_NAME *dns_name,
                        const UCHAR *name_string, UINT length);

说明

此服务用于初始化 X.509 DNS 名称,以便与某些需要特定名称格式的 API 服务一起使用。 例如,nx_secure_tls_sni_extension_parse 服务需要一个 NX_SECURE_X509_DNS_NAME 对象,以便与 TLS 握手期间服务器名称指示扩展中的远程主机提供的名称相匹配。 DNS 名称只是包含长度的字符串,DNS 名称的最大允许长度(和 NX_SECURE_X509_DNS_NAME 中内部缓冲区的大小)由宏 NX_SECURE_X509_DNS_NAME_MAX 控制(默认为 100 字节)。

参数

  • dns_name:要初始化的 DNS 名称结构。
  • name_string:DNS 名称字符串数据。
  • length:名称字符串的长度。

返回值

  • UX_SUCCESS (0x00):初始化成功。
  • NX_SECURE_X509_NAME_STRING_TOO_LONG (0x19E):给定的名称字符串超过了 NX_SECURE_X509_DNS_NAME_MAX。
  • NX_PTR_ERROR (0X07):尝试使用的指针无效。

允许来自

线程数

示例

NX_SECURE_X509_DNS_NAME dns_name;

/* Initialize DNS name. */
status = nx_secure_x509_dns_name_initialize(&dns_name, “www.example.com”,
                                            strlen(“www.example.com”);

/* Use initialized DNS name to send the Server Name Indication extension to the
   remote TLS server. */
status = nx_secure_tls_session_sni_extension_set(&tls_session, &dns_name);

另请参阅

  • nx_secure_tls_session_create
  • nx_secure_tls_session_sni_extension_parse
  • nx_secure_tls_session_sni_extension_set

nx_secure_x509_extended_key_usage_extension_parse

在 X.509 证书中查找并分析 X.509 扩展密钥用法扩展

原型

UINT  nx_secure_x509_extended_key_usage_extension_parse(
                        NX_SECURE_X509_CERT *certificate,
                        UINT key_usage);

说明

此服务应该从证书验证回调内调用(请参阅 nx_secure_tls_session_certificate_callback_set)。 它将在 X.509 证书中搜索特定的扩展密钥用法 OID,并返回该 OID 是否存在。 key_usage 参数是 OID 的整数映射,可供 NetX Secure X.509 和 TLS 在内部使用,用于避免将可变长度 OID 字符串作为参数传递。

下表给出了扩展密钥用法扩展的相关 OID。 要检查收到的 TLS 服务器证书中的扩展密钥用法的典型 TLS 客户端实现将检查是否存在 OID NX_SECURE_TLS_X509_TYPE_PKIX_KP_SERVER_AUTH,如果该扩展存在但 OID 不存在,则该证书将被视为无效,无法将主机标识为 TLS 服务器,此时证书验证回调应返回错误。 如果扩展本身缺失,则由应用程序决定是否继续执行 TLS 握手。

在证书验证回调中,错误返回代码 NX_SECURE_X509_KEY_USAGE_ERROR 预留给应用程序使用。 如果检查密钥用法时出错,则可能从回调返回此值,用于指出失败的原因。

NetX Secure 标识符 OID 值 说明
NX_SECURE_TLS_X509_TYPE_PKIX_KP_SERVER_AUTH 1.3.6.1.5.5.7.3.1 证书可用于标识 TLS 服务器
NX_SECURE_TLS_X509_TYPE_PKIX_KP_CLIENT_AUTH 1.3.6.1.5.5.7.3.2 证书可用于标识 TLS 客户端
NX_SECURE_TLS_X509_TYPE_PKIX_KP_CODE_SIGNING 1.3.6.1.5.5.7.3.3 证书可用于为代码签名
NX_SECURE_TLS_X509_TYPE_PKIX_KP_EMAIL_PROTECT 1.3.6.1.5.5.7.3.4 证书可用于为电子邮件签名
NX_SECURE_TLS_X509_TYPE_PKIX_KP_TIME_STAMPING 1.3.6.1.5.5.7.3.8 证书可用于为时间戳签名
NX_SECURE_TLS_X509_TYPE_PKIX_KP_OCSP_SIGNING 1.3.6.1.5.5.7.3.9 证书可用于为 OCSP 响应签名

用于 X.509 扩展密钥用法扩展的 OID 和映射

参数

  • certificate:指向正在验证的证书的指针。
  • key_usage:上表中的 OID 整数映射。

返回值

  • NX_SUCCESS (0x00):找到了指定的密钥用法 OID。
  • NX_SECURE_X509_MULTIBYTE_TAG_UNSUPPORTED (0x181):遇到了 ASN.1 多字节标记(不支持的证书)。
  • NX_SECURE_X509_ASN1_LENGTH_TOO_LONG (0X182):遇到了无效的 ASN.1 字段(无效的证书)。
  • NX_SECURE_X509_INVALID_TAG_CLASS (0x190):遇到了无效的 ASN.1 标记类(无效的证书)。
  • NX_SECURE_X509_INVALID_EXTENSION_SEQUENCE (0x192):遇到了无效的扩展(无效的证书)。
  • NX_SECURE_X509_EXTENSION_NOT_FOUND (0x19B):在提供的证书中找不到扩展密钥用法扩展。
  • NX_PTR_ERROR (0x07):证书指针无效。

允许来自

线程数

示例

ULONG certificate_verification_callback(NX_SECURE_TLS_SESSION *session, NX_SECURE_X509_CERT* certificate)
{
UINT status;

    /* Extended key usage - look for specific OIDs. */
    status = nx_secure_x509_extended_key_usage_extension_parse(certificate,
                        NX_SECURE_TLS_X509_TYPE_PKIX_KP_SERVER_AUTH);

    if(status != NX_SUCCESS)
    {
        if(NX_SECURE_X509_EXT_KEY_USAGE_NOT_FOUND)
        {
            printf("Extended key usage extension not found or specified key usage OID not
                    provided in extension.\n");
            /* The certificate was valid but the specified OID was not found. The
               application can decide whether to continue or abort the TLS handshake. */
            return(NX_SECURE_X509_KEY_USAGE_ERROR);
        }
        else
        {
            /* The extension or certificate was invalid. */
            return(status);
        }
    }

    /* The specified OID was found, return success! */
    return(NX_SUCCESS);
}

另请参阅

  • nx_secure_tls_session_certificate_callback_set
  • nx_secure_x509_key_usage_extension_parse
  • nx_secure_x509_crl_revocation_check
  • nx_secure_x509_common_name_dns_check
  • nx_secure_x509_extension_find

nx_secure_x509_extension_find

在 X.509 证书中查找并返回 X.509 扩展

原型

UINT  nx_secure_x509_extension_find(
                        NX_SECURE_X509_CERT *certificate,
                        NX_SECURE_X509_EXTENSION *extension,
                        USHORT extension_id);

说明

此服务应该在证书验证回调中调用(请参阅 nx_secure_tls_session_certificate_callback_set),它是高级 X.509 服务。

此函数将基于 OID 搜索 X.509 证书中的特定扩展,并返回该 OID 是否存在以及包含对相关原始扩展数据的引用的结构。 extension_id 参数是 OID 的整数映射,可供 NetX Secure X.509 和 TLS 在内部使用,用于避免将可变长度 OID 字符串作为参数传递。

为特定扩展提供的帮助程序函数(例如 nx_secure_x509_key_usage_extension_parse)在内部调用 nx_secure_x509_extension_find 以获取扩展数据。

下表给出了已知 X.509 扩展名的相关 OID。

NX_SECURE_X509_EXTENSION 结构包含指向 X.509 证书的指针,该证书允许帮助程序函数(如 nx_secure_x509_key_usage_extension_parse)快速解码采用 DER 编码的原始扩展 ASN.1 数据。

有关特定扩展的信息,请参阅 RFC 5280(X.509 规范)或相应帮助程序函数的引用(如果可用)。

当前版本的 NetX Secure X.509 为 X.509 扩展提供有限支持。 将来会添加更多帮助程序函数。

重要

此服务是一项高级功能,适用于熟悉 X.509 扩展和 DER 编码 ASN.1 的用户。 之所以提供此服务,是为了让这些用户能够访问 NetX Secure X.509 当前未提供帮助程序函数的扩展。 对于不包含帮助程序函数的扩展,你必须自行分析原始 DER 编码的 ASN.1。

NetX Secure 标识符 OID 值 说明 帮助程序函数?
NX_SECURE_TLS_X509_TYPE_DIRECTORY_ATTRIBUTES 2.5.29.9 目录属性 - 关于证书使用者的基本信息属性
NX_SECURE_TLS_X509_TYPE_SUBJECT_KEY_ID 2.5.29.14 用于标识特定公钥
NX_SECURE_TLS_X509_TYPE_KEY_USAGE 2.5.29.15 提供有关证书公钥的有效用法的信息
NX_SECURE_TLS_X509_TYPE_SUBJECT_ALT_NAME 2.5.29.17 提供用于标识证书的备用 DNS 名称 24
NX_SECURE_TLS_X509_TYPE_ISSUER_ALT_NAME 2.5.29.18 提供标识证书颁发者的备用 DNS 名称
NX_SECURE_TLS_X509_TYPE_BASIC_CONSTRAINTS 2.5.29.19 提供基本的证书使用限制信息
NX_SECURE_TLS_X509_TYPE_NAME_CONSTRAINTS 2.5.29.30 用于将证书名称限制为特定域
NX_SECURE_TLS_X509_TYPE_CRL_DISTRIBUTION 2.5.29.31 提供用于 CRL 分发的 URI
NX_SECURE_TLS_X509_TYPE_CERTIFICATE_POLICIES 2.5.29.32 大型 PKI 系统的证书策略列表
NX_SECURE_TLS_X509_TYPE_CERT_POLICY_MAPPINGS 2.5.29.33 CA 证书策略列表
NX_SECURE_TLS_X509_TYPE_AUTHORITY_KEY_ID 2.5.29.35 用于标识与证书签名关联的特定公钥
NX_SECURE_TLS_X509_TYPE_POLICY_CONSTRAINTS 2.5.29.36 CA 策略限制
NX_SECURE_TLS_X509_TYPE_EXTENDED_KEY_USAGE 2.5.29.37 基于 OID 的密钥用法的其他信息
NX_SECURE_TLS_X509_TYPE_FRESHEST_CRL 2.5.29.46 提供用于获取增量 CRL 的信息
NX_SECURE_TLS_X509_TYPE_INHIBIT_ANYPOLICY 2.5.29.54 指示无法使用 AnyPolicy 的 CA 证书字段

用于 X.509 扩展的 OID 和映射

  1. SubjectAltName 扩展在服务 nx_secure_x509_common_name_dns_check 中作为 DNS 名称检查的一部分进行分析。

参数

  • certificate:指向正在验证的证书的指针。
  • extension:返回包含扩展数据指针和长度的结构。
  • extension_id:上表中的 OID 整数映射。

返回值

  • NX_SUCCESS (0x00):找到了指定的扩展 OID,并返回了数据。
  • NX_SECURE_X509_MULTIBYTE_TAG_UNSUPPORTED (0x181):遇到了 ASN.1 多字节标记(不支持的证书)。
  • NX_SECURE_X509_ASN1_LENGTH_TOO_LONG (0X182):遇到了无效的 ASN.1 字段(无效的证书)。
  • NX_SECURE_X509_INVALID_TAG_CLASS (0x190):遇到了无效的 ASN.1 标记类(无效的证书)。
  • NX_SECURE_X509_INVALID_EXTENSION_SEQUENCE (0x192):遇到了无效的扩展。
  • NX_SECURE_X509_EXTENSION_NOT_FOUND (0x19B):在提供的证书中找不到指定的 OID 扩展。
  • NX_PTR_ERROR (0x07):证书或扩展指针无效。

允许来自

线程数

示例

/* Function to parse a Basic Constraints X.509 extension. */
UINT _basic_constraints_extension_parse(NX_SECURE_X509_CERT *certificate)
{
const UCHAR             *current_buffer;
ULONG                    length;
UINT                     status;
NX_SECURE_X509_EXTENSION extension_data;

    /* Find the Basic Constraints extension in the certificate. */
    status = _nx_secure_x509_extension_find(certificate, &extension_data,
                              NX_SECURE_TLS_X509_TYPE_BASIC_CONSTRAINTS);

    /* See if extension present - it might be OK if not present! */
    if (status != NX_SUCCESS)
    {
        return(status);
    }

    /* The extension_data structure now points to the raw extension ASN.1
      (DER-encoded). */
    current_buffer = extension_data.nx_secure_x509_extension_data;
    length = extension_data.nx_secure_x509_extension_data_length;

   /* Extension ASN.1 parsing… */

   return(NX_SUCCESS);
}

另请参阅

  • nx_secure_tls_session_certificate_callback_set
  • nx_secure_x509_key_usage_extension_parse
  • nx_secure_x509_crl_revocation_check
  • nx_secure_x509_common_name_dns_check
  • nx_secure_x509_extended_key_usage_extension_parse

nx_secure_x509_key_usage_extension_parse

在 X.509 证书中查找并分析 X.509 密钥用法扩展

原型

UINT  nx_secure_x509_key_usage_extension_parse(
                        NX_SECURE_X509_CERT *certificate,
                        USHORT *bitfield);

说明

此服务应该从证书验证回调内调用(请参阅 nx_secure_tls_session_certificate_callback_set)。 它将搜索密钥用法扩展,如果已找到,将返回“位域”参数中的密钥用法位域。

下表提供了 X.509 规范 (RFC 5280) 定义的位。 使用适当的位掩码(并检查非零设置)的按位与操作将为每位提供值。

请注意,位域的 DER 编码会去除额外的零,因此原始证书数据中位的实际位置可能与它们在已解码位域中的位置不同。 提供的位掩码应该只在由 nx_secure_x509_key_usage_extension_parse 返回的已解码的位域中使用,而不与采用 DER 编码的原始证书数据一起使用。

在证书验证回调中,错误返回代码 NX_SECURE_X509_KEY_USAGE_ERROR 预留给应用程序使用。 如果检查密钥用法时出错,则可能从回调返回此值,用于指出失败的原因。

NetX Secure 标识符 位位置 说明
NX_SECURE_X509_KEY_USAGE_DIGITAL_SIGNATURE 0 证书可用于数字签名
NX_SECURE_X509_KEY_USAGE_NON_REPUDIATION 1 证书可用于验证数字签名,而不是证书和 CRL 的数字签名
NX_SECURE_X509_KEY_USAGE_KEY_ENCIPHERMENT 2 证书可用于加密对称密钥(密钥传输)
NX_SECURE_X509_KEY_USAGE_DATA_ENCIPHERMENT 3 证书可用于直接加密原始用户数据(罕见)
NX_SECURE_X509_KEY_USAGE_KEY_AGREEMENT 4 证书可用于密钥协议(与 Diffie-Hellman 一样)
NX_SECURE_X509_KEY_USAGE_KEY_CERT_SIGN 5 证书可用于对其他证书进行签名和验证(证书是 CA 或 ICA 证书)。
NX_SECURE_X509_KEY_USAGE_CRL_SIGN 6 证书公钥用于验证 CRL 上的签名
NX_SECURE_X509_KEY_USAGE_ENCIPHER_ONLY 7 用于密钥协议位(位 4)– 设置之后,证书密钥只能用于在密钥协议期间进行加密。 如果未设置密钥协议位,则未定义。
NX_SECURE_X509_KEY_USAGE_DECIPHER_ONLY 8 用于密钥协议位(位 4)– 设置之后,证书密钥只能用于在密钥协议期间进行解密。 如果未设置密钥协议位,则未定义。

X.509 密钥用法扩展的位掩码和值

参数

  • certificate:指向正在验证的证书的指针。
  • bitfield:从扩展中返回整个位域。

返回值

  • NX_SUCCESS (0x00):找到了密钥用法扩展,并返回了位域。
  • NX_SECURE_X509_MULTIBYTE_TAG_UNSUPPORTED (0x181):遇到了 ASN.1 多字节标记(不支持的证书)。
  • NX_SECURE_X509_ASN1_LENGTH_TOO_LONG (0X182):遇到了无效的 ASN.1 字段(无效的证书)。
  • NX_SECURE_X509_INVALID_TAG_CLASS (0x190):遇到了无效的 ASN.1 标记类(无效的证书)。
  • NX_SECURE_X509_INVALID_EXTENSION_SEQUENCE (0x192):遇到了无效的扩展(无效的证书)。
  • NX_SECURE_X509_EXTENSION_NOT_FOUND (0x19B):在提供的证书中找不到密钥用法扩展。
  • NX_PTR_ERROR (0x07):证书或位域指针无效。

允许来自

线程数

示例

ULONG certificate_verification_callback(NX_SECURE_TLS_SESSION *session,
  NX_SECURE_X509_CERT* certificate)
{
UINT status;
USHORT key_usage_bitfield;

    /* Key usage – extract key usage bitfield. */
    status = nx_secure_x509_key_usage_extension_parse(certificate, &key_usage_bitfield);

   /* Check certificate for a few specific key usage bits. */
   if((key_usage_bitfield & NX_SECURE_X509_KEY_USAGE_DIGITAL_SIGNATURE) == 0 ||
      (key_usage_bitfield & NX_SECURE_X509_KEY_USAGE_NON_REPUDIATION)   == 0 ||
      (key_usage_bitfield & NX_SECURE_X509_KEY_USAGE_KEY_ENCIPHERMENT)  == 0)
    {
        printf("Expected key usage bitfield bits not set!\n");
        return(NX_SECURE_X509_KEY_USAGE_ERROR);
    }

    /* The specified bits were set, return success! */
    return(NX_SUCCESS);
}

另请参阅

  • nx_secure_tls_session_certificate_callback_set
  • nx_secure_x509_extended_key_usage_extension_parse
  • nx_secure_x509_crl_revocation_check
  • nx_secure_x509_common_name_dns_check
  • nx_secure_x509_extension_find