Compartilhar via


Diretrizes do desenvolvedor

Este tópico discute diretrizes gerais para desenvolvedores que trabalham com e/ou desenvolvem minidrivers de cartão inteligentes – para que você saiba o comportamento esperado da cartão inteligente e seus aplicativos associados.

Diretrizes gerais de design

Para obter informações sobre como distribuir minidrivers cartão, como mapear sistemas de arquivos cartão lógicos e outras diretrizes de design de minidriver, consulte a seção Diretrizes gerais de design em Visão geral do Minidriver de Cartão Inteligente.

Método challenge/response de desbloqueio de PIN de cartão inteligente

Para que um administrador use esse mecanismo com êxito para desbloquear a cartão de um usuário, os administradores devem ser capazes de identificar e usar a chave de administrador armazenada no cartão para que possam gerar corretamente os dados de resposta para o desafio que foi emitido.

Uma maneira de fazer isso é usar o identificador cartão para identificar exclusivamente o cartão. (O identificador cartão é um identificador exclusivo para um cartão.) Isso pode ser representado de alguma forma para os usuários na interface do usuário, mas, caso contrário, um programa pode ser gravado para enviar comandos APDU apropriados ao cartão para ler essas informações.

Essas informações podem permitir que o administrador identifique a chave secreta no cartão e calcule a resposta apropriada aos dados de desafio emitidos aos usuários.

Supõe-se que a chave secreta de administrador armazenada em um cartão seja mantida usando algum mecanismo seguro acessível apenas para administradores válidos e confiáveis (preferencialmente o menor número possível). No entanto, isso está além do escopo dessa especificação.

Para obter mais informações, consulte a seção "Mecanismo de Desafio/Resposta" a seguir.

Suporte a PIN aprimorado

A versão 6.0 dá suporte a uma arquitetura flexível para vários suporte a PIN. Essa arquitetura introduziu um novo conceito de funções em que cada função corresponde a um identificador de PIN. Os identificadores de PIN são usados para extrair informações de PIN do cartão, bem como para associar um PIN a um contêiner de chaves.

O identificador consiste em um número, atualmente limitado a 0 a 7. Também introduzimos a noção de um PIN_SET, que é uma máscara de bits que pode ser gerada a partir do identificador de PIN. Atualmente, apenas os 8 bits inferiores são usados para o conjunto de PIN. Também podemos optar por usar os bits restantes para indicar condições como 'and', 'or' ou outras informações que podemos achar úteis no futuro. Escolhemos essa abordagem para que a máscara de bits seja fácil para o cartão impor.

Suponha que o usuário se autentique com a função 3, correspondente ao PIN nº 3. Isso se traduz na máscara de bits 0000 0100 (base 2). O cartão pode registrá-lo como a ID autenticada no momento e pode verificar facilmente as regras de controle de acesso em chaves e PINs fazendo uma operação AND bit a bit. O design permite ter várias identidades autenticadas no cartão simultaneamente, e esse é um requisito para cartões que dão suporte a minidrivers v6 cartão. Por exemplo, se o PIN nº 1 for autenticado e, posteriormente, o PIN #2 for autenticado, as operações que qualquer um desses controles PINs deverão ser permitidas.

PINs de sessão e canal PIN seguro

Quando o Windows deve estabelecer um canal PIN seguro para autenticação de PIN, a sequência de operações a seguir é executada com o minidriver. Para cumprir, um minidriver e o cartão devem ser compatíveis com a sequência a seguir. Em particular, os PINs de sessão devem ser transferíveis entre processos e durar apenas por um determinado período de tempo. (Recomendamos que qualquer PIN de sessão seja válido até que a redefinição a frio do cartão usando o sinalizador CARD_AUTHENTICATE_ SESSION_PIN mesmo que CardAuthenticateEx seja chamado com o sinalizador GENERATE_SESSION_PIN definido.)

O seguinte comportamento deve ter suporte:

  1. O aplicativo A, um processo de sistema confiável, adquire um identificador para a cartão inteligente e coleta um PIN.
  2. Em seguida, o aplicativo A chama a função cartão minidriver CardAuthenticateEx e passa o PIN que foi coletado e define o sinalizador CARD_AUTHENTICATE_GENERATE_SESSION_PIN. Isso não faz com que o cartão seja desbloqueado.
  3. O aplicativo A armazena o PIN de sessão que foi gerado e libera o identificador para o cartão e cartão minidriver. O cartão não é redefinição a frio.
  4. O aplicativo A envia o PIN da sessão e o nome do leitor que tem o cartão adquirido na etapa 1 para o Aplicativo B.
  5. O aplicativo B adquire o mesmo cartão que em 1.
  6. O aplicativo B chama CardAuthenticateEx e passa o PIN da sessão e define o sinalizador CARD_AUTHENTICATE_SESSION_PIN. Se o PIN da sessão ainda for válido, o cartão deverá ser autenticado e válido para uso.
  7. Quando o Aplicativo B terminar de usar o cartão, ele chamará CardDeauthenticateEx para desautorizar o cartão.

Esse comportamento tem as seguintes limitações práticas:

  • Os cartões devem declarar sua capacidade de trabalhar com PINs de sessão retornando o valor apropriado para CP_CARD_PIN_STRENGTH_VERIFY.

  • Os cartões que dependem de ter o PIN para cada verificação não são compatíveis com esse sistema.

  • Vários aplicativos podem ter o que determinam ser PINs de sessão válidos de uma só vez. Se apenas um PIN de sessão for possível para cada PIN, a seguinte implementação será aconselhada:

    • O cartão deve se lembrar do PIN de sessão mais recente que foi gerado.
    • Se um PIN de sessão inválido for apresentado, o cartão deverá falhar na autenticação e, se houver suporte, decrementar o contador de repetição para o PIN da sessão. Se a contagem de repetições atingir 0 e a próxima tentativa de autenticação for inválida, o PIN da sessão deverá ser invalidado.
    • As apresentações de PIN de sessão subsequentes devem falhar até que um novo PIN de sessão seja negociado.
  • O PIN de sessão deve ser capaz de ser usado de diferentes aplicativos no sistema.

  • O PIN da sessão não deve ser simplesmente uma codificação do PIN.

  • A segurança desse sistema é limitada à força do PIN de sessão e ao protocolo de negociação usado para gerá-lo. A negociação real do PIN da sessão está fora do escopo dessa especificação. Não fazemos nenhum requisito no design, exceto que ele funciona conforme descrito nesta seção.

  • O PIN da sessão ainda é considerado valioso e deve ser tratado como um segredo.

  • O cartão deve ser capaz de detectar um PIN de sessão inválido.

Cartões somente leitura

Para cartões de endereço personalizados fora do ambiente CSP/KSP base e que são inerentemente somente leitura, introduzimos um novo conceito de cartões somente leitura. Se um cartão for somente leitura, ele deverá anunciar isso por meio da função CardGetProperty (consulte esta seção anteriormente nesta especificação).

Os cartões somente leitura devem dar suporte apenas a um subconjunto da versão 7 cartão interface do minidriver e não são necessários para dar suporte a um PIN de administrador.

A tabela a seguir lista as funções que um cartão somente leitura deve dar suporte.

Nome da função Obrigatório Observações
Cardacquirecontext Sim
CardDeleteContext Sim
CardAuthenticatePin Sim
CardGetChallenge Não (opcional)
CardAuthenticateChallenge Não (opcional)
CardDeauthenticate Sim (opcional)
CardUnblockPin Não (opcional)
CardChangeAuthenticator Não (opcional)
CardCreateDirectory Não
CardDeleteDirectory Não
CardReadFile Sim O minidriver de cartão deve emular um sistema de arquivos.
CardCreateFile No
CardGetFileInfo Sim O minidriver de cartão deve emular um sistema de arquivos.
CardWriteFile No
CardDeleteFile Não
CardEnumFiles Sim O minidriver de cartão deve emular um sistema de arquivos.
CardQueryFreeSpace Sim O minidriver de cartão deve emular um sistema de arquivos.
CardQueryCapabilities Sim O minidriver de cartão deve emular um sistema de arquivos.
CardCreateContainer No
CardCreateContainerEx Não (opcional)
CardDeleteContainer Não
CardGetContainerInfo Sim
CardRSADecrypt Sim (opcional)
CardConstructDHAgreement Sim (opcional)
CardDeriveKey Sim (opcional)
CardDestroyDHAgreement Sim (opcional)
CardSignData Sim
CardQueryKeySizes Sim
CardAuthenticateEx Sim
CardChangeAuthenticatorEx Não (opcional)
CardDeauthenticateEx Sim
CardGetChallengeEx Não (opcional)
CardGetContainerProperty Sim
CardSetContainerProperty Não
CardGetProperty Sim
CardSetProperty Sim
MDImportSessionKey Não (opcional)
MDEncryptData Não (opcional)
CardImportSessionKey Não (opcional)
CardGetSharedKeyHandle Não (opcional)
CardGetAlgorithmProperty Não (opcional)
CardGetKeyProperty Não (opcional)
CardSetKeyProperty Não (opcional)
CardDestroyKey Não (opcional)
CardProcessEncryptedData Não (opcional)
Legenda
Sim Essa função deve ser implementada.
Não O ponto de entrada deve existir e deve retornar SCARD_E_UNSUPPORTED_FEATURE.
Não (opcional) A operação não precisa ter suporte para uma cartão somente leitura, mas pode ser implementada se o cartão der suporte à operação. Se não houver suporte, o ponto de entrada deverá retornar SCARD_E_UNSUPPORTED_FEATURE.
Sim (opcional) Essa função deve ser implementada de acordo com sua definição nessa especificação, independentemente de o cartão ser somente leitura.

Os seguintes requisitos devem ser considerados ao desenvolver um minidriver para um cartão somente leitura:

  • Todos os arquivos CSP/KSP base esperados, com exceção do arquivo 'msroots' (como 'cardcf' e 'cardid') devem existir no cartão somente leitura (ou devem ser virtualizados por meio da interface do minidriver).
  • Um cartão somente leitura deve conter pelo menos uma chave no cartão protegido pelo PIN de cartão primário (ou seja, ROLE_USER).
  • Uma cartão somente leitura tem permissão para não conter uma chave de administrador. Se essa for a situação, espera-se que o minidriver não dê suporte a CardGetChallenge, CardAuthenticateChallenge e CardUnblockPin.
  • Quando consultado, um cartão somente leitura deve retornar 0 bytes disponíveis e 0 contêineres disponíveis.
  • Somente as propriedades CP_PARENT_WINDOW e CP_PIN_CONTEXT_STRING devem ter permissão para serem definidas em um cartão somente leitura.
  • Para um cartão somente leitura, a propriedade CP_SUPPORTS_WIN_X509_ENROLLMENT deve ser false.

Modos de cache

O CSP/KSP base dá suporte a três modos diferentes de cache, dependendo do modo de cache retornado pelo CardGetProperty chamado com o parâmetro CP_CARD_CACHE_MODE:

  • Se o sinalizador retornado for CP_CACHE_MODE_GLOBAL_CACHE e o cartão relatou a propriedade CP_READ_ONLY_CARD como TRUE, o cache de dados CSP/KSP base será um cache global. Se o cartão for somente leitura, o CSP/KSP base não gravará no arquivo cardcf. Se o cartão puder ser gravado no CSP/KSP base, ele funcionará como hoje.
  • Para obter mais informações sobre CP_CARD_CACHE_MODE e CP_CACHE_MODE_GLOBAL_CACHE, consulte CardGetProperty.
  • Quando o sinalizador retornado é CP_CACHE_MODE_SESSION_ONLY, o CSP/KSP base opera para que o cache de dados seja limpo quando detectar que o cartão foi removido ou reinserido. Em outras palavras, definimos uma sessão para ser o intervalo entre cartão inserção e remoção.
  • O cache também é implementado para cada processo e não é global. Esse modo foi projetado para cartões somente leitura que não são alterados no computador de um usuário, mas sim em alguma estação governamental ou outro site externo. (Esse modo tem suporte para cartões de leitura/gravação, mas recomendamos o cache global para esses cartões.)
  • Se o cartão for somente leitura e houver uma chance de que o cartão seja alterado no computador do usuário (por meio de outro meio que não seja o CSP/KSP base), o aplicativo deverá usar o modo sem cache descrito posteriormente nesta especificação para evitar a situação em que o cache pode conter dados obsoletos.
  • Quando o sinalizador é CP_CACHE_MODE_NO_CACHE, o CSP/KSP base não implementa nenhum cache de dados. Esse modo foi projetado para cartão minidrivers que não dão suporte à gravação do arquivo cardcf, mas onde o estado cartão pode ser alterado. O minidriver cartão decide se deseja fazer algum cache em sua camada.

Mecanismo de desafio/resposta

A interface do minidriver cartão dá suporte a um mecanismo de autenticação de desafio/resposta. O cartão deve gerar um desafio de um ou mais blocos de 8 bytes. A entidade de autenticação calcula a resposta criptografando o desafio usando o DES Triplo (3DES) que opera no modo CBC com uma chave de 168 bits (e ignorando os bits de paridade).

O cartão verifica a resposta usando um dos seguintes métodos:

  • Repetindo a operação de criptografia no desafio emitido anteriormente e comparando os resultados.
  • Descriptografando a resposta e comparando o resultado com o desafio.

Se os valores resultantes forem os mesmos, a autenticação será bem-sucedida.

O cartão e a entidade de autenticação devem usar a mesma chave simétrica.

O código de exemplo a seguir detalha como a entidade de autenticação pode calcular a resposta. Esse código não abrange nenhuma garantia associada e é fornecido apenas como um exemplo e diretrizes.

#include <windows.h>
#include <wincrypt.h>
#include <winscard.h>
#include <stdlib.h>
#include <stdio.h>
#include <memory.h>


int __cdecl wmain(int argc, __in_ecount(argc) WCHAR **wargv)
{
    //Acquire the context Use CryptAcquireContext

    HCRYPTPROV hProv= 0;
    DWORD dwMode=CRYPT_MODE_ECB;
    BYTE *pbLocData = NULL,tempbyte;
    DWORD cbLocData = 8, count = 0;
    HCRYPTKEY hKey = 0;
    BYTE rgEncByte [] = {0xA8,0x92,0xD7,0x56,0x01,0x61,0x7C,0x5D };

    BYTE DesKeyBlob [] = {
        0x08, 0x02, 0x00, 0x00, 0x03, 0x66, 0x00, 0x00,
        0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00
    };

    pbLocData = (BYTE *) malloc (sizeof(BYTE)*cbLocData);
    memcpy(pbLocData,rgEncByte,cbLocData);

    if (!CryptAcquireContext(
            &hProv,
            NULL,
            L"Microsoft Enhanced Cryptographic Provider V1.0",
            PROV_RSA_FULL,
            CRYPT_VERIFYCONTEXT))
    {
        printf("Acquire context failed with 0x%08x \n", GetLastError());
        goto Cleanup;
    }
    if (!CryptImportKey(
            hProv,
            DesKeyBlob,
            sizeof(DesKeyBlob),
            0,
            0,
            &hKey ) )
    {
        printf("Error 0x%08x in importing the 3Des key \n", GetLastError());
        goto Cleanup;
    }
    if (!CryptSetKeyParam(
            hKey,
            KP_MODE,
            (BYTE *)&dwMode,
            0))
    {
        printf("Error 0x%08x in CryptSetKeyParam \n", GetLastError());
        goto Cleanup;
    }
    if (!CryptEncrypt(
            hKey,
            0,
            FALSE,
            0,
            pbLocData,
            &cbLocData,
            cbLocData))
    {
        printf("Error 0x%08x in CryptEncrypt call \n", GetLastError());
        goto Cleanup;
    }

    for (count=0; count < cbLocData; ++count)
    {
        printf("0x%02x",pbLocData[count]);
    }
    printf("\n");

Cleanup:    
    if (hKey)
    {
        CryptDestroyKey(hKey);
        hKey = 0;
    }
    if (pbLocData)
    {
        free(pbLocData);
        pbLocData = NULL;
    }
    if (hProv)
    {
        CryptReleaseContext(hProv,0);
    }

    return 0;
}

Interoperabilidade com msroots

O arquivo msroots é um repositório de certificados formatado PKCS nº 7 para raízes confiáveis da empresa. (O arquivo é um recipiente de certificados com conteúdo vazio e uma assinatura vazia e é gravado e lido pelo CSP base.) Os desenvolvedores de minidriver de cartão não precisam escrever nenhum código especial no minidriver cartão para lidar com esse arquivo. Ao armazenar certificados no arquivo msroots, propriedades como CODE_SIGNING EKU não são propagadas para o cartão inteligente porque o arquivo msroots armazena certificados em um formato diferente dos repositórios de computadores. Os desenvolvedores que desejam ler ou gravar esse arquivo de outros aplicativos podem usar os snippets de código de exemplo a seguir para acessar os dados.

Operações de leitura

if (FALSE == CryptQueryObject(CERT_QUERY_OBJECT_BLOB,
                                &dbStore,
                                CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED,
                                CERT_QUERY_FORMAT_FLAG_BINARY,
                                0,
                                NULL,
                                NULL,
                                NULL,
                                phCertStore,
                                NULL,
                                NULL))
{
    dwSts = GetLastError();
}

Operações de gravação

// Serialize the store

if (FALSE == CertSaveStore( hCertStore,
                            PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
                            CERT_STORE_SAVE_AS_PKCS7,
                            CERT_STORE_SAVE_TO_MEMORY,
                            &dbStore,
                            0))
{
    dwSts = GetLastError();
    goto Ret;
}

dbStore.pbData = CspAllocH(dbStore.cbData);

if (NULL == dbStore.pbData)
{
    dwSts = ERROR_NOT_ENOUGH_MEMORY;
    goto Ret;
}

if (FALSE == CertSaveStore( hCertStore,
                            PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
                            CERT_STORE_SAVE_AS_PKCS7,
                            CERT_STORE_SAVE_TO_MEMORY,
                            &dbStore,
                            0))
{
    dwSts = GetLastError();
    goto Ret;
}

Configurações de Política de Grupo para csp de cartão inteligente base da Microsoft

Política de Grupo configurações do Provedor de Serviços de Criptografia de Cartão Inteligente Base da Microsoft estão localizadas em [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography\Defaults \Provider\Microsoft Base Smart Card Crypto Provider].

Chave Descrição
DefaultPrivateKeyLenBits

dword:00000400

Parâmetro de geração de chave padrão — chave de 1024 bits.

RequireOnCardPrivateKeyGen

dword:00000000

Isso define o sinalizador para exigir cartão geração de chave privada (padrão). Se esse valor for definido, a chave gerada em um host poderá ser importada para o cartão. Isso é usado para cartões que não dão suporte à geração de chaves cartão ou em que a caução de chave é necessária.

TransactionTimeoutMilliseconds

dword:000005dc

1500, 1,5 segundos é o tempo limite padrão para manter transações no cartão.

AllowPrivateSignatureKeyImport

dword:00000000

Permite importar chaves de assinatura, ou seja, cenários de arquivamento de chave.

AllowPrivateExchangeKeyImport

dword:00000000

Permite importar chaves de troca, ou seja, cenários de arquivamento de chave.

Configurações de Política de Grupo para O KSP do Cartão Inteligente CNG da Microsoft

Política de Grupo Configurações do Provedor de Armazenamento de Chaves de Cartão Inteligente do Microsoft CNG estão localizadas em [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Cryptography \Providers\Microsoft Smart Card Key Storage Provider].

Chave Descrição
DefaultPrivateKeyLenBits

dword:00000400

Parâmetro de geração de chave padrão — chave de 1024 bits.

RequireOnCardPrivateKeyGen

dword:00000000

Isso define o sinalizador para exigir cartão geração de chave privada (padrão). Se esse valor for definido, a chave gerada em um host poderá ser importada para o cartão. Isso é usado para cartões que não dão suporte à geração de chaves cartão ou em que a caução de chave é necessária.

TransactionTimeoutMilliseconds

dword:000005dc

1500, 1,5 segundos é o tempo limite padrão para manter transações no cartão.

AllowPrivateSignatureKeyImport

dword:00000000

Permite importar chaves de assinatura, ou seja, cenários de arquivamento de chave.

AllowPrivateExchangeKeyImport

dword:00000000

Permite importar chaves de troca, ou seja, cenários de arquivamento de chave.

AllocPrivateECDHEKeyImport

dword:00000000

Permite importar chaves ECDH, ou seja, principais cenários de arquivamento

AllowPrivateECDSAKeyImport

dword:00000000

Permite importar chaves ECDSA, ou seja, principais cenários de arquivamento

Considerações especiais

  • No Windows Vista com Service Pack 1 (SP1), enquanto o sistema operacional está em execução no modo de segurança, nenhuma operação de cartão inteligente necessária para PIN é possível, além do logon do Windows.

  • Chamar CryptAcquireContext com um dos seguintes sinalizadores solicita autenticação de PIN com USER_PIN independentemente do PIN real atribuído ao contêiner:

    • CRYPT_NEWKEYSET
    • CRYPT_DEFAULT_CONTAINER_OPTIONAL
    • CRYPT_DELETEKEYSET
    • CRYPT_VERIFYCONTEXT
  • CardDeleteContext pode ser chamado mesmo depois que DllMain foi chamado com DLL_PROCESS_DETACH.