421 lines
8.3 KiB
C++
421 lines
8.3 KiB
C++
//+--------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 1996 - 1999
|
|
//
|
|
// File: crypt.cpp
|
|
//
|
|
// Contents: Cert Server wrapper routines
|
|
//
|
|
// History: 17-Oct-96 vich created
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
#include <pch.cpp>
|
|
|
|
#pragma hdrstop
|
|
|
|
#include <stdlib.h>
|
|
|
|
#define CRYPT32_SP3_ONLY
|
|
|
|
#ifdef CRYPT32_SP3_ONLY
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
#include "keygen.h"
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#include "crypttls.h"
|
|
#include "ossconv.h"
|
|
#include "ossutil.h"
|
|
|
|
// All the *pInfo extra stuff needs to be aligned
|
|
#define INFO_LEN_ALIGN(Len) (((Len) + 7) & ~7)
|
|
|
|
HCRYPTOSSGLOBAL hOssGlobal;
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Function: GetPog
|
|
//
|
|
// Synopsis: Initialize thread local storage for the asn libs
|
|
//
|
|
// Returns: pointer to an initialized OssGlobal data structure
|
|
//--------------------------------------------------------------------------
|
|
|
|
__inline OssGlobal *
|
|
GetPog(VOID)
|
|
{
|
|
return(I_CryptGetOssGlobal(hOssGlobal));
|
|
}
|
|
|
|
|
|
HRESULT
|
|
HError(VOID)
|
|
{
|
|
HRESULT hr;
|
|
|
|
hr = GetLastError();
|
|
if (hr <= 0xffff)
|
|
{
|
|
hr = HRESULT_FROM_WIN32(hr);
|
|
}
|
|
|
|
if (!FAILED(hr))
|
|
{
|
|
// somebody failed a call without properly setting an error condition
|
|
|
|
hr = E_UNEXPECTED;
|
|
}
|
|
return(hr);
|
|
}
|
|
|
|
|
|
VOID
|
|
OssX509GetIA5ConvertedToUnicode(
|
|
IN IA5STRING *pOss,
|
|
IN DWORD dwFlags,
|
|
OPTIONAL OUT LPWSTR *ppwsz,
|
|
IN OUT BYTE **ppbExtra,
|
|
IN OUT LONG *plRemainExtra)
|
|
{
|
|
OssUtilGetIA5StringConvertedToUnicode(
|
|
pOss->length,
|
|
pOss->value,
|
|
dwFlags,
|
|
ppwsz,
|
|
ppbExtra,
|
|
plRemainExtra);
|
|
}
|
|
|
|
|
|
VOID
|
|
OssX509GetObjectId(
|
|
IN ObjectID *pOss,
|
|
IN DWORD dwFlags,
|
|
OPTIONAL OUT CHAR **pInfo,
|
|
IN OUT BYTE **ppbExtra,
|
|
IN OUT LONG *plRemainExtra)
|
|
{
|
|
DWORD cb;
|
|
DWORD cbExtra;
|
|
char ach[MAX_PATH];
|
|
LONG lRemainExtra;
|
|
|
|
cb = sizeof(ach);
|
|
if (!OssConvFromObjectIdentifier(pOss->count, pOss->value, ach, &cb))
|
|
{
|
|
goto error;
|
|
}
|
|
CSASSERT(strlen(ach) + 1 == cb);
|
|
cbExtra = INFO_LEN_ALIGN(cb);
|
|
|
|
lRemainExtra = *plRemainExtra;
|
|
lRemainExtra -= cbExtra;
|
|
if (0 <= lRemainExtra)
|
|
{
|
|
*pInfo = (char *) *ppbExtra;
|
|
CopyMemory(*pInfo, ach, cb);
|
|
*ppbExtra += cbExtra;
|
|
}
|
|
*plRemainExtra = lRemainExtra;
|
|
|
|
error:
|
|
;
|
|
}
|
|
|
|
|
|
__inline VOID
|
|
OssX509GetAlgorithmParameters(
|
|
IN OpenType *pOss,
|
|
IN DWORD dwFlags,
|
|
OPTIONAL OUT CRYPT_OBJID_BLOB *pInfo,
|
|
IN OUT BYTE **ppbExtra,
|
|
IN OUT LONG *plRemainExtra)
|
|
{
|
|
OssUtilGetOctetString(
|
|
pOss->length,
|
|
(BYTE *) pOss->encoded,
|
|
dwFlags,
|
|
pInfo,
|
|
ppbExtra,
|
|
plRemainExtra);
|
|
}
|
|
|
|
|
|
VOID
|
|
OssX509GetAlgorithm(
|
|
IN AlgorithmIdentifier *pOss,
|
|
IN DWORD dwFlags,
|
|
OPTIONAL OUT CRYPT_ALGORITHM_IDENTIFIER *pInfo,
|
|
IN OUT BYTE **ppbExtra,
|
|
IN OUT LONG *plRemainExtra)
|
|
{
|
|
if (0 <= *plRemainExtra)
|
|
{
|
|
ZeroMemory((VOID *) pInfo, sizeof(*pInfo));
|
|
}
|
|
OssX509GetObjectId(
|
|
&pOss->algorithm,
|
|
dwFlags,
|
|
&pInfo->pszObjId,
|
|
ppbExtra,
|
|
plRemainExtra);
|
|
|
|
if (pOss->bit_mask & parameters_present)
|
|
{
|
|
OssX509GetAlgorithmParameters(
|
|
&pOss->parameters,
|
|
dwFlags,
|
|
&pInfo->Parameters,
|
|
ppbExtra,
|
|
plRemainExtra);
|
|
}
|
|
}
|
|
|
|
|
|
__inline VOID
|
|
OssX509GetPublicKeyBlob(
|
|
IN BITSTRING const *pOss,
|
|
IN DWORD dwFlags,
|
|
OPTIONAL OUT CRYPT_BIT_BLOB *pInfo,
|
|
IN OUT BYTE **ppbExtra,
|
|
IN OUT LONG *plRemainExtra)
|
|
{
|
|
OssUtilGetBitString(
|
|
pOss->length,
|
|
pOss->value,
|
|
dwFlags,
|
|
pInfo,
|
|
ppbExtra,
|
|
plRemainExtra);
|
|
}
|
|
|
|
|
|
VOID
|
|
OssX509GetPublicKeyInfo(
|
|
IN SubjectPublicKeyInfo *pOss,
|
|
IN DWORD dwFlags,
|
|
OPTIONAL OUT CERT_PUBLIC_KEY_INFO *pInfo,
|
|
IN OUT BYTE **ppbExtra,
|
|
IN OUT LONG *plRemainExtra)
|
|
{
|
|
OssX509GetAlgorithm(
|
|
&pOss->algorithm,
|
|
dwFlags,
|
|
&pInfo->Algorithm,
|
|
ppbExtra,
|
|
plRemainExtra);
|
|
|
|
OssX509GetPublicKeyBlob(
|
|
&pOss->subjectPublicKey,
|
|
dwFlags,
|
|
&pInfo->PublicKey,
|
|
ppbExtra,
|
|
plRemainExtra);
|
|
}
|
|
//+-------------------------------------------------------------------------
|
|
// Decode into an allocated, OSS formatted info structure
|
|
//
|
|
// Called by the OssX509*Decode() functions.
|
|
//--------------------------------------------------------------------------
|
|
|
|
__inline BOOL
|
|
OssInfoDecodeAndAlloc(
|
|
IN int pdunum,
|
|
IN const BYTE *pbEncoded,
|
|
IN DWORD cbEncoded,
|
|
OUT VOID **ppOssInfo)
|
|
{
|
|
return(OssUtilDecodeAndAllocInfo(
|
|
GetPog(),
|
|
pdunum,
|
|
pbEncoded,
|
|
cbEncoded,
|
|
ppOssInfo));
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// Free an allocated, OSS formatted info structure
|
|
//
|
|
// Called by the OssX509*Decode() functions.
|
|
//--------------------------------------------------------------------------
|
|
|
|
VOID
|
|
OssInfoFree(
|
|
IN int pdunum,
|
|
IN VOID *pOssInfo)
|
|
{
|
|
if (NULL != pOssInfo)
|
|
{
|
|
DWORD dwErr = GetLastError();
|
|
|
|
// TlsGetValue globbers LastError
|
|
OssUtilFreeInfo(GetPog(), pdunum, pOssInfo);
|
|
SetLastError(dwErr);
|
|
}
|
|
}
|
|
|
|
|
|
//+-------------------------------------------------------------------------
|
|
// KeyGen Info Decode (OSS X509)
|
|
//--------------------------------------------------------------------------
|
|
|
|
BOOL
|
|
DecodeKeyGen(
|
|
IN BYTE const *pbEncoded,
|
|
IN DWORD cbEncoded,
|
|
IN DWORD dwFlags,
|
|
OUT VOID *pInfo,
|
|
IN OUT DWORD *pcbInfo)
|
|
{
|
|
BOOL fResult = FALSE;
|
|
HRESULT hr;
|
|
SignedPublicKeyAndChallenge *pOssInfo = NULL;
|
|
CERT_KEYGEN_REQUEST_INFO *pcgi;
|
|
BYTE *pbExtra;
|
|
LONG lRemainExtra;
|
|
LONG lAlignExtra;
|
|
|
|
if (pInfo == NULL)
|
|
{
|
|
*pcbInfo = 0;
|
|
}
|
|
if (0 == hOssGlobal)
|
|
{
|
|
hOssGlobal = I_CryptInstallOssGlobal(keygen, 0, NULL);
|
|
if (0 == hOssGlobal)
|
|
{
|
|
goto error;
|
|
}
|
|
}
|
|
if (!OssInfoDecodeAndAlloc(
|
|
SignedPublicKeyAndChallenge_PDU,
|
|
pbEncoded,
|
|
cbEncoded,
|
|
(VOID **) &pOssInfo))
|
|
{
|
|
hr = HError();
|
|
printf("OssInfoDecodeAndAlloc returned %u (%x)\n", hr, hr);
|
|
goto error;
|
|
}
|
|
|
|
lRemainExtra = (LONG) *pcbInfo - INFO_LEN_ALIGN(sizeof(*pcgi));
|
|
pbExtra = NULL;
|
|
|
|
// for lRemainExtra < 0, LENGTH_ONLY calculation
|
|
|
|
if (0 <= lRemainExtra)
|
|
{
|
|
pcgi = (CERT_KEYGEN_REQUEST_INFO *) pInfo;
|
|
|
|
// Default all optional fields to zero
|
|
ZeroMemory((VOID *) pcgi, sizeof(*pcgi));
|
|
pcgi->dwVersion = 1;
|
|
|
|
pbExtra = (BYTE *) pcgi + INFO_LEN_ALIGN(sizeof(*pcgi));
|
|
}
|
|
|
|
OssX509GetPublicKeyInfo(
|
|
&pOssInfo->publicKeyAndChallenge.spki,
|
|
dwFlags,
|
|
&pcgi->SubjectPublicKeyInfo,
|
|
&pbExtra,
|
|
&lRemainExtra);
|
|
|
|
OssX509GetIA5ConvertedToUnicode(
|
|
&pOssInfo->publicKeyAndChallenge.challenge,
|
|
dwFlags,
|
|
&pcgi->pwszChallengeString,
|
|
&pbExtra,
|
|
&lRemainExtra);
|
|
|
|
if (0 <= lRemainExtra)
|
|
{
|
|
*pcbInfo = *pcbInfo - (DWORD) lRemainExtra;
|
|
}
|
|
else
|
|
{
|
|
*pcbInfo = *pcbInfo + (DWORD) -lRemainExtra;
|
|
if (NULL != pInfo)
|
|
{
|
|
SetLastError(HRESULT_FROM_WIN32(ERROR_MORE_DATA));
|
|
goto error;
|
|
}
|
|
}
|
|
fResult = TRUE;
|
|
|
|
error:
|
|
OssInfoFree(SignedPublicKeyAndChallenge_PDU, pOssInfo);
|
|
if (!fResult)
|
|
{
|
|
*pcbInfo = 0;
|
|
}
|
|
return(fResult);
|
|
}
|
|
#endif
|
|
|
|
|
|
BOOL
|
|
myDecodeKeyGenRequest(
|
|
IN BYTE const *pbRequest,
|
|
IN DWORD cbRequest,
|
|
OUT CERT_KEYGEN_REQUEST_INFO **ppKeyGenRequest,
|
|
OUT DWORD *pcbKeyGenRequest)
|
|
{
|
|
BOOL fOk = FALSE;
|
|
|
|
#ifdef CRYPT32_SP3_ONLY
|
|
*ppKeyGenRequest = NULL;
|
|
*pcbKeyGenRequest = 0;
|
|
|
|
if (!DecodeKeyGen(
|
|
pbRequest,
|
|
cbRequest,
|
|
0, // dwFlags
|
|
NULL,
|
|
pcbKeyGenRequest))
|
|
{
|
|
goto error;
|
|
}
|
|
*ppKeyGenRequest = (CERT_KEYGEN_REQUEST_INFO *) LocalAlloc(LMEM_FIXED, *pcbKeyGenRequest);
|
|
if (NULL == *ppKeyGenRequest)
|
|
{
|
|
_PrintError(E_OUTOFMEMORY, "LocalAlloc(KeyGenRequest)");
|
|
SetLastError(E_OUTOFMEMORY);
|
|
goto error;
|
|
}
|
|
|
|
if (!DecodeKeyGen(
|
|
pbRequest,
|
|
cbRequest,
|
|
0, // dwFlags
|
|
*ppKeyGenRequest,
|
|
pcbKeyGenRequest))
|
|
{
|
|
goto error;
|
|
}
|
|
#else
|
|
if (!myDecodeObject(
|
|
X509_ASN_ENCODING,
|
|
X509_KEYGEN_REQUEST_TO_BE_SIGNED,
|
|
pbRequest,
|
|
cbRequest,
|
|
(VOID **) ppKeyGenRequest,
|
|
pcbKeyGenRequest))
|
|
{
|
|
err = myHLastError();
|
|
_JumpError(err, error, "myDecodeObject");
|
|
}
|
|
#endif
|
|
fOk = TRUE;
|
|
|
|
error:
|
|
return(fOk);
|
|
}
|