windows-nt/Source/XPSP1/NT/ds/security/services/ca/certlib/keygen2.cpp
2020-09-26 16:20:57 +08:00

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);
}