2 * IPRT - Crypto - PEM-file Reader & Writer.
6 * Copyright (C) 2006-2024 Oracle and/or its affiliates.
8 * This file is part of VirtualBox base platform packages, as
9 * available from https://www.virtualbox.org.
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation, in version 3 of the
16 * This program is distributed in the hope that it will be useful, but
17 * WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 * The contents of this file may alternatively be used under the terms
25 * of the Common Development and Distribution License Version 1.0
26 * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
27 * in the VirtualBox distribution, in which case the provisions of the
28 * CDDL are applicable instead of those of the GPL.
30 * You may elect to license modified versions of this file under the
31 * terms and conditions of either the GPL or the CDDL or both.
33 * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
36 #ifndef IPRT_INCLUDED_crypto_pem_h
37 #define IPRT_INCLUDED_crypto_pem_h
38 #ifndef RT_WITHOUT_PRAGMA_ONCE
42 #include <iprt/types.h>
43 #include <iprt/asn1.h> /* PRTASN1CORE */
44 #include <iprt/string.h> /* PFNRTSTROUTPUT */
49 /** @defgroup grp_rt_spc RTCrPem - PEM-file Reader & Writer
50 * @ingroup grp_rt_crypto
56 * One PEM marker word (use RT_STR_TUPLE to initialize).
58 typedef struct RTCRPEMMARKERWORD
60 /** The word string. */
65 /** Pointer to a const marker word. */
66 typedef RTCRPEMMARKERWORD
const *PCRTCRPEMMARKERWORD
;
72 * This is an array of words with lengths, optimized for avoid unnecessary
73 * strlen() while searching the file content. It is ASSUMED that all PEM
74 * section markers starts with either 'BEGIN' or 'END', followed by the words
75 * in the this structure.
77 typedef struct RTCRPEMMARKER
79 /** Pointer to an array of marker words. */
80 PCRTCRPEMMARKERWORD paWords
;
81 /** Number of works in the array papszWords points to. */
84 /** Pointer to a const PEM marker. */
85 typedef RTCRPEMMARKER
const *PCRTCRPEMMARKER
;
91 typedef struct RTCRPEMFIELD
93 /** Pointer to the next field. */
94 struct RTCRPEMFIELD
const *pNext
;
95 /** The field value. */
97 /** The field value length. */
99 /** The field name length. */
101 /** The field name. */
102 RT_FLEXIBLE_ARRAY_EXTENSION
103 char szName
[RT_FLEXIBLE_ARRAY
];
105 /** Pointer to a PEM field. */
106 typedef RTCRPEMFIELD
*PRTCRPEMFIELD
;
107 /** Pointer to a const PEM field. */
108 typedef RTCRPEMFIELD
const *PCRTCRPEMFIELD
;
114 * The API works on linked lists of these.
116 typedef struct RTCRPEMSECTION
118 /** Pointer to the next file section. */
119 struct RTCRPEMSECTION
const *pNext
;
120 /** The marker for this section. NULL if binary file. */
121 PCRTCRPEMMARKER pMarker
;
122 /** Pointer to the binary data. */
124 /** The size of the binary data. */
126 /** List of fields, NULL if none. */
127 PCRTCRPEMFIELD pFieldHead
;
128 /** Set if RTCRPEMREADFILE_F_SENSITIVE was specified. */
131 /** Pointer to a PEM section. */
132 typedef RTCRPEMSECTION
*PRTCRPEMSECTION
;
133 /** Pointer to a const PEM section. */
134 typedef RTCRPEMSECTION
const *PCRTCRPEMSECTION
;
138 * Frees sections returned by RTCrPemReadFile and RTCrPemParseContent.
139 * @returns IPRT status code.
140 * @param pSectionHead The first section.
142 RTDECL(int) RTCrPemFreeSections(PCRTCRPEMSECTION pSectionHead
);
145 * Parses the given data and returns a list of binary sections.
147 * If the file isn't an ASCII file or if no markers were found, the entire file
148 * content is returned as one single section (with pMarker = NULL).
150 * @returns IPRT status code.
151 * @retval VINF_EOF if the file is empty. The @a ppSectionHead value will be
153 * @retval VWRN_NOT_FOUND no section was found and RTCRPEMREADFILE_F_ONLY_PEM
154 * is specified. The @a ppSectionHead value will be NULL.
156 * @param pvContent The content bytes to parse.
157 * @param cbContent The number of content bytes.
158 * @param fFlags RTCRPEMREADFILE_F_XXX.
159 * @param paMarkers Array of one or more section markers to look for.
160 * @param cMarkers Number of markers in the array.
161 * @param ppSectionHead Where to return the head of the section list. Call
162 * RTCrPemFreeSections to free.
163 * @param pErrInfo Where to return extend error info. Optional.
165 RTDECL(int) RTCrPemParseContent(void const *pvContent
, size_t cbContent
, uint32_t fFlags
,
166 PCRTCRPEMMARKER paMarkers
, size_t cMarkers
, PCRTCRPEMSECTION
*ppSectionHead
, PRTERRINFO pErrInfo
);
169 * Reads the content of the given file and returns a list of binary sections
172 * If the file isn't an ASCII file or if no markers were found, the entire file
173 * content is returned as one single section (with pMarker = NULL).
175 * @returns IPRT status code.
176 * @retval VINF_EOF if the file is empty. The @a ppSectionHead value will be
178 * @retval VWRN_NOT_FOUND no section was found and RTCRPEMREADFILE_F_ONLY_PEM
179 * is specified. The @a ppSectionHead value will be NULL.
181 * @param pszFilename The path to the file to read.
182 * @param fFlags RTCRPEMREADFILE_F_XXX.
183 * @param paMarkers Array of one or more section markers to look for.
184 * @param cMarkers Number of markers in the array.
185 * @param ppSectionHead Where to return the head of the section list. Call
186 * RTCrPemFreeSections to free.
187 * @param pErrInfo Where to return extend error info. Optional.
189 RTDECL(int) RTCrPemReadFile(const char *pszFilename
, uint32_t fFlags
, PCRTCRPEMMARKER paMarkers
, size_t cMarkers
,
190 PCRTCRPEMSECTION
*ppSectionHead
, PRTERRINFO pErrInfo
);
191 /** @name RTCRPEMREADFILE_F_XXX - Flags for RTCrPemReadFile and
192 * RTCrPemParseContent.
194 /** Continue on encoding error. */
195 #define RTCRPEMREADFILE_F_CONTINUE_ON_ENCODING_ERROR RT_BIT(0)
196 /** Only PEM sections, no binary fallback. */
197 #define RTCRPEMREADFILE_F_ONLY_PEM RT_BIT(1)
198 /** Sensitive data, use the safer allocator. */
199 #define RTCRPEMREADFILE_F_SENSITIVE RT_BIT(2)
201 #define RTCRPEMREADFILE_F_VALID_MASK UINT32_C(0x00000007)
205 * Finds the beginning of first PEM section using the specified markers.
207 * This will not look any further than the first section. Nor will it check for
210 * @returns Pointer to the "-----BEGIN XXXX" sequence on success.
212 * @param pvContent The content bytes to parse.
213 * @param cbContent The number of content bytes.
214 * @param paMarkers Array of one or more section markers to look for.
215 * @param cMarkers Number of markers in the array.
217 RTDECL(const char *) RTCrPemFindFirstSectionInContent(void const *pvContent
, size_t cbContent
,
218 PCRTCRPEMMARKER paMarkers
, size_t cMarkers
);
222 * PEM formatter for a binary data blob.
224 * @returns Number of output bytes (sum of @a pfnOutput return values).
225 * @param pfnOutput The output callback function.
226 * @param pvUser The user argument to the output callback.
227 * @param pvContent The binary blob to output.
228 * @param cbContent Size of the binary blob.
229 * @param pszMarker The PEM marker, .e.g "PRIVATE KEY", "CERTIFICATE" or
231 * @sa RTCrPemWriteAsn1, RTCrPemWriteAsn1ToVfsFile,
232 * RTCrPemWriteAsn1ToVfsFile
234 RTDECL(size_t) RTCrPemWriteBlob(PFNRTSTROUTPUT pfnOutput
, void *pvUser
,
235 const void *pvContent
, size_t cbContent
, const char *pszMarker
);
237 RTDECL(ssize_t
) RTCrPemWriteBlobToVfsIoStrm(RTVFSIOSTREAM hVfsIos
, const void *pvContent
, size_t cbContent
, const char *pszMarker
);
238 RTDECL(ssize_t
) RTCrPemWriteBlobToVfsFile(RTVFSFILE hVfsFile
, const void *pvContent
, size_t cbContent
, const char *pszMarker
);
241 * PEM formatter for a generic ASN.1 structure.
243 * This will call both RTAsn1EncodePrepare() and RTAsn1EncodeWrite() on
244 * @a pRoot. Uses DER encoding.
246 * @returns Number of outputted chars (sum of @a pfnOutput return values),
247 * negative values are error status codes from the ASN.1 encoding.
248 * @param pfnOutput The output callback function.
249 * @param pvUser The user argument to the output callback.
250 * @param fFlags Reserved, MBZ.
251 * @param pRoot The root of the ASN.1 to encode and format as PEM.
252 * @param pszMarker The PEM marker, .e.g "PRIVATE KEY", "CERTIFICATE" or
254 * @param pErrInfo For encoding errors. Optional.
255 * @sa RTCrPemWriteAsn1ToVfsFile, RTCrPemWriteAsn1ToVfsFile,
258 RTDECL(ssize_t
) RTCrPemWriteAsn1(PFNRTSTROUTPUT pfnOutput
, void *pvUser
, PRTASN1CORE pRoot
,
259 uint32_t fFlags
, const char *pszMarker
, PRTERRINFO pErrInfo
);
262 * PEM formatter for a generic ASN.1 structure and output it to @a hVfsIos.
264 * This will call both RTAsn1EncodePrepare() and RTAsn1EncodeWrite() on
265 * @a pRoot. Uses DER encoding.
267 * @returns Number of chars written, negative values are error status codes from
268 * the ASN.1 encoding or from RTVfsIoStrmWrite().
269 * @param hVfsIos Handle to the I/O stream to write it to.
270 * @param fFlags Reserved, MBZ.
271 * @param pRoot The root of the ASN.1 to encode and format as PEM.
272 * @param pszMarker The PEM marker, .e.g "PRIVATE KEY", "CERTIFICATE" or
274 * @param pErrInfo For encoding errors. Optional.
275 * @sa RTCrPemWriteAsn1ToVfsFile, RTCrPemWriteAsn1, RTCrPemWriteBlob
277 RTDECL(ssize_t
) RTCrPemWriteAsn1ToVfsIoStrm(RTVFSIOSTREAM hVfsIos
, PRTASN1CORE pRoot
,
278 uint32_t fFlags
, const char *pszMarker
, PRTERRINFO pErrInfo
);
281 * PEM formatter for a generic ASN.1 structure and output it to @a hVfsFile.
283 * This will call both RTAsn1EncodePrepare() and RTAsn1EncodeWrite() on
284 * @a pRoot. Uses DER encoding.
286 * @returns Number of chars written, negative values are error status codes from
287 * the ASN.1 encoding or from RTVfsIoStrmWrite().
288 * @param hVfsFile Handle to the file to write it to.
289 * @param fFlags Reserved, MBZ.
290 * @param pRoot The root of the ASN.1 to encode and format as PEM.
291 * @param pszMarker The PEM marker, .e.g "PRIVATE KEY", "CERTIFICATE" or
293 * @param pErrInfo For encoding errors. Optional.
294 * @sa RTCrPemWriteAsn1ToVfsIoStrm, RTCrPemWriteAsn1, RTCrPemWriteBlob
296 RTDECL(ssize_t
) RTCrPemWriteAsn1ToVfsFile(RTVFSFILE hVfsFile
, PRTASN1CORE pRoot
,
297 uint32_t fFlags
, const char *pszMarker
, PRTERRINFO pErrInfo
);
303 #endif /* !IPRT_INCLUDED_crypto_pem_h */