summaryrefslogtreecommitdiffstats
path: root/include/iprt/crypto/pem.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/iprt/crypto/pem.h')
-rw-r--r--include/iprt/crypto/pem.h304
1 files changed, 304 insertions, 0 deletions
diff --git a/include/iprt/crypto/pem.h b/include/iprt/crypto/pem.h
new file mode 100644
index 00000000..c36bc587
--- /dev/null
+++ b/include/iprt/crypto/pem.h
@@ -0,0 +1,304 @@
+/** @file
+ * IPRT - Crypto - PEM-file Reader & Writer.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_crypto_pem_h
+#define IPRT_INCLUDED_crypto_pem_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/types.h>
+#include <iprt/asn1.h> /* PRTASN1CORE */
+#include <iprt/string.h> /* PFNRTSTROUTPUT */
+
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_rt_spc RTCrPem - PEM-file Reader & Writer
+ * @ingroup grp_rt_crypto
+ * @{
+ */
+
+
+/**
+ * One PEM marker word (use RT_STR_TUPLE to initialize).
+ */
+typedef struct RTCRPEMMARKERWORD
+{
+ /** The word string. */
+ const char *pszWord;
+ /** The length. */
+ uint32_t cchWord;
+} RTCRPEMMARKERWORD;
+/** Pointer to a const marker word. */
+typedef RTCRPEMMARKERWORD const *PCRTCRPEMMARKERWORD;
+
+
+/**
+ * A PEM marker.
+ *
+ * This is an array of words with lengths, optimized for avoid unnecessary
+ * strlen() while searching the file content. It is ASSUMED that all PEM
+ * section markers starts with either 'BEGIN' or 'END', followed by the words
+ * in the this structure.
+ */
+typedef struct RTCRPEMMARKER
+{
+ /** Pointer to an array of marker words. */
+ PCRTCRPEMMARKERWORD paWords;
+ /** Number of works in the array papszWords points to. */
+ uint32_t cWords;
+} RTCRPEMMARKER;
+/** Pointer to a const PEM marker. */
+typedef RTCRPEMMARKER const *PCRTCRPEMMARKER;
+
+
+/**
+ * A PEM field.
+ */
+typedef struct RTCRPEMFIELD
+{
+ /** Pointer to the next field. */
+ struct RTCRPEMFIELD const *pNext;
+ /** The field value. */
+ char const *pszValue;
+ /** The field value length. */
+ size_t cchValue;
+ /** The field name length. */
+ size_t cchName;
+ /** The field name. */
+ RT_FLEXIBLE_ARRAY_EXTENSION
+ char szName[RT_FLEXIBLE_ARRAY];
+} RTCRPEMFIELD;
+/** Pointer to a PEM field. */
+typedef RTCRPEMFIELD *PRTCRPEMFIELD;
+/** Pointer to a const PEM field. */
+typedef RTCRPEMFIELD const *PCRTCRPEMFIELD;
+
+
+/**
+ * A PEM section.
+ *
+ * The API works on linked lists of these.
+ */
+typedef struct RTCRPEMSECTION
+{
+ /** Pointer to the next file section. */
+ struct RTCRPEMSECTION const *pNext;
+ /** The marker for this section. NULL if binary file. */
+ PCRTCRPEMMARKER pMarker;
+ /** Pointer to the binary data. */
+ uint8_t *pbData;
+ /** The size of the binary data. */
+ size_t cbData;
+ /** List of fields, NULL if none. */
+ PCRTCRPEMFIELD pFieldHead;
+ /** Set if RTCRPEMREADFILE_F_SENSITIVE was specified. */
+ bool fSensitive;
+} RTCRPEMSECTION;
+/** Pointer to a PEM section. */
+typedef RTCRPEMSECTION *PRTCRPEMSECTION;
+/** Pointer to a const PEM section. */
+typedef RTCRPEMSECTION const *PCRTCRPEMSECTION;
+
+
+/**
+ * Frees sections returned by RTCrPemReadFile and RTCrPemParseContent.
+ * @returns IPRT status code.
+ * @param pSectionHead The first section.
+ */
+RTDECL(int) RTCrPemFreeSections(PCRTCRPEMSECTION pSectionHead);
+
+/**
+ * Parses the given data and returns a list of binary sections.
+ *
+ * If the file isn't an ASCII file or if no markers were found, the entire file
+ * content is returned as one single section (with pMarker = NULL).
+ *
+ * @returns IPRT status code.
+ * @retval VINF_EOF if the file is empty. The @a ppSectionHead value will be
+ * NULL.
+ * @retval VWRN_NOT_FOUND no section was found and RTCRPEMREADFILE_F_ONLY_PEM
+ * is specified. The @a ppSectionHead value will be NULL.
+ *
+ * @param pvContent The content bytes to parse.
+ * @param cbContent The number of content bytes.
+ * @param fFlags RTCRPEMREADFILE_F_XXX.
+ * @param paMarkers Array of one or more section markers to look for.
+ * @param cMarkers Number of markers in the array.
+ * @param ppSectionHead Where to return the head of the section list. Call
+ * RTCrPemFreeSections to free.
+ * @param pErrInfo Where to return extend error info. Optional.
+ */
+RTDECL(int) RTCrPemParseContent(void const *pvContent, size_t cbContent, uint32_t fFlags,
+ PCRTCRPEMMARKER paMarkers, size_t cMarkers, PCRTCRPEMSECTION *ppSectionHead, PRTERRINFO pErrInfo);
+
+/**
+ * Reads the content of the given file and returns a list of binary sections
+ * found in the file.
+ *
+ * If the file isn't an ASCII file or if no markers were found, the entire file
+ * content is returned as one single section (with pMarker = NULL).
+ *
+ * @returns IPRT status code.
+ * @retval VINF_EOF if the file is empty. The @a ppSectionHead value will be
+ * NULL.
+ * @retval VWRN_NOT_FOUND no section was found and RTCRPEMREADFILE_F_ONLY_PEM
+ * is specified. The @a ppSectionHead value will be NULL.
+ *
+ * @param pszFilename The path to the file to read.
+ * @param fFlags RTCRPEMREADFILE_F_XXX.
+ * @param paMarkers Array of one or more section markers to look for.
+ * @param cMarkers Number of markers in the array.
+ * @param ppSectionHead Where to return the head of the section list. Call
+ * RTCrPemFreeSections to free.
+ * @param pErrInfo Where to return extend error info. Optional.
+ */
+RTDECL(int) RTCrPemReadFile(const char *pszFilename, uint32_t fFlags, PCRTCRPEMMARKER paMarkers, size_t cMarkers,
+ PCRTCRPEMSECTION *ppSectionHead, PRTERRINFO pErrInfo);
+/** @name RTCRPEMREADFILE_F_XXX - Flags for RTCrPemReadFile and
+ * RTCrPemParseContent.
+ * @{ */
+/** Continue on encoding error. */
+#define RTCRPEMREADFILE_F_CONTINUE_ON_ENCODING_ERROR RT_BIT(0)
+/** Only PEM sections, no binary fallback. */
+#define RTCRPEMREADFILE_F_ONLY_PEM RT_BIT(1)
+/** Sensitive data, use the safer allocator. */
+#define RTCRPEMREADFILE_F_SENSITIVE RT_BIT(2)
+/** Valid flags. */
+#define RTCRPEMREADFILE_F_VALID_MASK UINT32_C(0x00000007)
+/** @} */
+
+/**
+ * Finds the beginning of first PEM section using the specified markers.
+ *
+ * This will not look any further than the first section. Nor will it check for
+ * binaries.
+ *
+ * @returns Pointer to the "-----BEGIN XXXX" sequence on success.
+ * NULL if not found.
+ * @param pvContent The content bytes to parse.
+ * @param cbContent The number of content bytes.
+ * @param paMarkers Array of one or more section markers to look for.
+ * @param cMarkers Number of markers in the array.
+ */
+RTDECL(const char *) RTCrPemFindFirstSectionInContent(void const *pvContent, size_t cbContent,
+ PCRTCRPEMMARKER paMarkers, size_t cMarkers);
+
+
+/**
+ * PEM formatter for a binary data blob.
+ *
+ * @returns Number of output bytes (sum of @a pfnOutput return values).
+ * @param pfnOutput The output callback function.
+ * @param pvUser The user argument to the output callback.
+ * @param pvContent The binary blob to output.
+ * @param cbContent Size of the binary blob.
+ * @param pszMarker The PEM marker, .e.g "PRIVATE KEY", "CERTIFICATE" or
+ * similar.
+ * @sa RTCrPemWriteAsn1, RTCrPemWriteAsn1ToVfsFile,
+ * RTCrPemWriteAsn1ToVfsFile
+ */
+RTDECL(size_t) RTCrPemWriteBlob(PFNRTSTROUTPUT pfnOutput, void *pvUser,
+ const void *pvContent, size_t cbContent, const char *pszMarker);
+
+RTDECL(ssize_t) RTCrPemWriteBlobToVfsIoStrm(RTVFSIOSTREAM hVfsIos, const void *pvContent, size_t cbContent, const char *pszMarker);
+RTDECL(ssize_t) RTCrPemWriteBlobToVfsFile(RTVFSFILE hVfsFile, const void *pvContent, size_t cbContent, const char *pszMarker);
+
+/**
+ * PEM formatter for a generic ASN.1 structure.
+ *
+ * This will call both RTAsn1EncodePrepare() and RTAsn1EncodeWrite() on
+ * @a pRoot. Uses DER encoding.
+ *
+ * @returns Number of outputted chars (sum of @a pfnOutput return values),
+ * negative values are error status codes from the ASN.1 encoding.
+ * @param pfnOutput The output callback function.
+ * @param pvUser The user argument to the output callback.
+ * @param fFlags Reserved, MBZ.
+ * @param pRoot The root of the ASN.1 to encode and format as PEM.
+ * @param pszMarker The PEM marker, .e.g "PRIVATE KEY", "CERTIFICATE" or
+ * similar.
+ * @param pErrInfo For encoding errors. Optional.
+ * @sa RTCrPemWriteAsn1ToVfsFile, RTCrPemWriteAsn1ToVfsFile,
+ * RTCrPemWriteBlob
+ */
+RTDECL(ssize_t) RTCrPemWriteAsn1(PFNRTSTROUTPUT pfnOutput, void *pvUser, PRTASN1CORE pRoot,
+ uint32_t fFlags, const char *pszMarker, PRTERRINFO pErrInfo);
+
+/**
+ * PEM formatter for a generic ASN.1 structure and output it to @a hVfsIos.
+ *
+ * This will call both RTAsn1EncodePrepare() and RTAsn1EncodeWrite() on
+ * @a pRoot. Uses DER encoding.
+ *
+ * @returns Number of chars written, negative values are error status codes from
+ * the ASN.1 encoding or from RTVfsIoStrmWrite().
+ * @param hVfsIos Handle to the I/O stream to write it to.
+ * @param fFlags Reserved, MBZ.
+ * @param pRoot The root of the ASN.1 to encode and format as PEM.
+ * @param pszMarker The PEM marker, .e.g "PRIVATE KEY", "CERTIFICATE" or
+ * similar.
+ * @param pErrInfo For encoding errors. Optional.
+ * @sa RTCrPemWriteAsn1ToVfsFile, RTCrPemWriteAsn1, RTCrPemWriteBlob
+ */
+RTDECL(ssize_t) RTCrPemWriteAsn1ToVfsIoStrm(RTVFSIOSTREAM hVfsIos, PRTASN1CORE pRoot,
+ uint32_t fFlags, const char *pszMarker, PRTERRINFO pErrInfo);
+
+/**
+ * PEM formatter for a generic ASN.1 structure and output it to @a hVfsFile.
+ *
+ * This will call both RTAsn1EncodePrepare() and RTAsn1EncodeWrite() on
+ * @a pRoot. Uses DER encoding.
+ *
+ * @returns Number of chars written, negative values are error status codes from
+ * the ASN.1 encoding or from RTVfsIoStrmWrite().
+ * @param hVfsFile Handle to the file to write it to.
+ * @param fFlags Reserved, MBZ.
+ * @param pRoot The root of the ASN.1 to encode and format as PEM.
+ * @param pszMarker The PEM marker, .e.g "PRIVATE KEY", "CERTIFICATE" or
+ * similar.
+ * @param pErrInfo For encoding errors. Optional.
+ * @sa RTCrPemWriteAsn1ToVfsIoStrm, RTCrPemWriteAsn1, RTCrPemWriteBlob
+ */
+RTDECL(ssize_t) RTCrPemWriteAsn1ToVfsFile(RTVFSFILE hVfsFile, PRTASN1CORE pRoot,
+ uint32_t fFlags, const char *pszMarker, PRTERRINFO pErrInfo);
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !IPRT_INCLUDED_crypto_pem_h */
+