2 * Copyright 2007 Juan Lang
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 #include "wine/debug.h"
25 WINE_DEFAULT_DEBUG_CHANNEL(crypt
);
27 /* Called when a message's ref count reaches zero. Free any message-specific
30 typedef void (*CryptMsgCloseFunc
)(HCRYPTMSG msg
);
32 typedef BOOL (*CryptMsgGetParamFunc
)(HCRYPTMSG hCryptMsg
, DWORD dwParamType
,
33 DWORD dwIndex
, void *pvData
, DWORD
*pcbData
);
35 typedef BOOL (*CryptMsgUpdateFunc
)(HCRYPTMSG hCryptMsg
, const BYTE
*pbData
,
36 DWORD cbData
, BOOL fFinal
);
38 typedef struct _CryptMsgBase
42 PCMSG_STREAM_INFO stream_info
;
44 CryptMsgCloseFunc close
;
45 CryptMsgUpdateFunc update
;
46 CryptMsgGetParamFunc get_param
;
49 static inline void CryptMsgBase_Init(CryptMsgBase
*msg
, DWORD dwFlags
,
50 PCMSG_STREAM_INFO pStreamInfo
)
53 msg
->open_flags
= dwFlags
;
54 msg
->stream_info
= pStreamInfo
;
55 msg
->finalized
= FALSE
;
58 typedef struct _CDataEncodeMsg
61 DWORD bare_content_len
;
65 static const BYTE empty_data_content
[] = { 0x04,0x00 };
67 static void CDataEncodeMsg_Close(HCRYPTMSG hCryptMsg
)
69 CDataEncodeMsg
*msg
= (CDataEncodeMsg
*)hCryptMsg
;
71 if (msg
->bare_content
!= empty_data_content
)
72 LocalFree(msg
->bare_content
);
75 static BOOL
CDataEncodeMsg_Update(HCRYPTMSG hCryptMsg
, const BYTE
*pbData
,
76 DWORD cbData
, BOOL fFinal
)
78 CDataEncodeMsg
*msg
= (CDataEncodeMsg
*)hCryptMsg
;
81 if (msg
->base
.finalized
)
82 SetLastError(CRYPT_E_MSG_ERROR
);
85 if (msg
->base
.open_flags
& CMSG_DETACHED_FLAG
)
86 SetLastError(E_INVALIDARG
);
88 SetLastError(CRYPT_E_MSG_ERROR
);
92 msg
->base
.finalized
= TRUE
;
94 SetLastError(E_INVALIDARG
);
97 CRYPT_DATA_BLOB blob
= { cbData
, (LPBYTE
)pbData
};
99 /* data messages don't allow non-final updates, don't bother
100 * checking whether data already exist, they can't.
102 ret
= CryptEncodeObjectEx(X509_ASN_ENCODING
, X509_OCTET_STRING
,
103 &blob
, CRYPT_ENCODE_ALLOC_FLAG
, NULL
, &msg
->bare_content
,
104 &msg
->bare_content_len
);
105 if (ret
&& msg
->base
.stream_info
)
106 FIXME("stream info unimplemented\n");
112 static BOOL
CDataEncodeMsg_GetParam(HCRYPTMSG hCryptMsg
, DWORD dwParamType
,
113 DWORD dwIndex
, void *pvData
, DWORD
*pcbData
)
119 case CMSG_CONTENT_PARAM
:
120 case CMSG_BARE_CONTENT_PARAM
:
124 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
129 static HCRYPTMSG
CDataEncodeMsg_Open(DWORD dwFlags
, const void *pvMsgEncodeInfo
,
130 LPSTR pszInnerContentObjID
, PCMSG_STREAM_INFO pStreamInfo
)
136 SetLastError(E_INVALIDARG
);
139 msg
= CryptMemAlloc(sizeof(CDataEncodeMsg
));
142 CryptMsgBase_Init((CryptMsgBase
*)msg
, dwFlags
, pStreamInfo
);
143 msg
->base
.close
= CDataEncodeMsg_Close
;
144 msg
->base
.update
= CDataEncodeMsg_Update
;
145 msg
->base
.get_param
= CDataEncodeMsg_GetParam
;
146 msg
->bare_content_len
= sizeof(empty_data_content
);
147 msg
->bare_content
= (LPBYTE
)empty_data_content
;
149 return (HCRYPTMSG
)msg
;
152 static inline const char *MSG_TYPE_STR(DWORD type
)
156 #define _x(x) case (x): return #x
160 _x(CMSG_SIGNED_AND_ENVELOPED
);
165 return wine_dbg_sprintf("unknown (%d)", type
);
169 HCRYPTMSG WINAPI
CryptMsgOpenToEncode(DWORD dwMsgEncodingType
, DWORD dwFlags
,
170 DWORD dwMsgType
, const void *pvMsgEncodeInfo
, LPSTR pszInnerContentObjID
,
171 PCMSG_STREAM_INFO pStreamInfo
)
173 HCRYPTMSG msg
= NULL
;
175 TRACE("(%08x, %08x, %08x, %p, %s, %p)\n", dwMsgEncodingType
, dwFlags
,
176 dwMsgType
, pvMsgEncodeInfo
, debugstr_a(pszInnerContentObjID
), pStreamInfo
);
178 if (GET_CMSG_ENCODING_TYPE(dwMsgEncodingType
) != PKCS_7_ASN_ENCODING
)
180 SetLastError(E_INVALIDARG
);
186 msg
= CDataEncodeMsg_Open(dwFlags
, pvMsgEncodeInfo
,
187 pszInnerContentObjID
, pStreamInfo
);
192 FIXME("unimplemented for type %s\n", MSG_TYPE_STR(dwMsgType
));
194 case CMSG_SIGNED_AND_ENVELOPED
:
196 /* defined but invalid, fall through */
198 SetLastError(CRYPT_E_INVALID_MSG_TYPE
);
203 HCRYPTMSG WINAPI
CryptMsgOpenToDecode(DWORD dwMsgEncodingType
, DWORD dwFlags
,
204 DWORD dwMsgType
, HCRYPTPROV hCryptProv
, PCERT_INFO pRecipientInfo
,
205 PCMSG_STREAM_INFO pStreamInfo
)
207 FIXME("(%08x, %08x, %08x, %08lx, %p, %p): stub\n", dwMsgEncodingType
,
208 dwFlags
, dwMsgType
, hCryptProv
, pRecipientInfo
, pStreamInfo
);
210 if (GET_CMSG_ENCODING_TYPE(dwMsgEncodingType
) != PKCS_7_ASN_ENCODING
)
212 SetLastError(E_INVALIDARG
);
218 HCRYPTMSG WINAPI
CryptMsgDuplicate(HCRYPTMSG hCryptMsg
)
220 TRACE("(%p)\n", hCryptMsg
);
224 CryptMsgBase
*msg
= (CryptMsgBase
*)hCryptMsg
;
226 InterlockedIncrement(&msg
->ref
);
231 BOOL WINAPI
CryptMsgClose(HCRYPTMSG hCryptMsg
)
233 TRACE("(%p)\n", hCryptMsg
);
237 CryptMsgBase
*msg
= (CryptMsgBase
*)hCryptMsg
;
239 if (InterlockedDecrement(&msg
->ref
) == 0)
241 TRACE("freeing %p\n", msg
);
250 BOOL WINAPI
CryptMsgUpdate(HCRYPTMSG hCryptMsg
, const BYTE
*pbData
,
251 DWORD cbData
, BOOL fFinal
)
253 CryptMsgBase
*msg
= (CryptMsgBase
*)hCryptMsg
;
256 TRACE("(%p, %p, %d, %d)\n", hCryptMsg
, pbData
, cbData
, fFinal
);
257 if (msg
&& msg
->update
)
258 ret
= msg
->update(hCryptMsg
, pbData
, cbData
, fFinal
);
262 BOOL WINAPI
CryptMsgGetParam(HCRYPTMSG hCryptMsg
, DWORD dwParamType
,
263 DWORD dwIndex
, void *pvData
, DWORD
*pcbData
)
265 CryptMsgBase
*msg
= (CryptMsgBase
*)hCryptMsg
;
268 TRACE("(%p, %d, %d, %p, %p)\n", hCryptMsg
, dwParamType
, dwIndex
,
270 if (msg
&& msg
->get_param
)
271 ret
= msg
->get_param(hCryptMsg
, dwParamType
, dwIndex
, pvData
, pcbData
);