VirtualBox

source: vbox/trunk/src/VBox/Runtime/common/crypto/key-file.cpp@ 73670

最後變更 在這個檔案從73670是 73665,由 vboxsync 提交於 7 年 前

IPRT,SUP,Main: Working on new crypto key handling and rsa signing. bugref:9152

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Author Date Id Revision
檔案大小: 12.1 KB
 
1/* $Id: key-file.cpp 73665 2018-08-14 17:49:23Z vboxsync $ */
2/** @file
3 * IPRT - Crypto - Cryptographic Keys, File I/O.
4 */
5
6/*
7 * Copyright (C) 2006-2018 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.alldomusa.eu.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 */
26
27
28/*********************************************************************************************************************************
29* Header Files *
30*********************************************************************************************************************************/
31#include "internal/iprt.h"
32#include <iprt/crypto/key.h>
33
34#include <iprt/asm.h>
35#include <iprt/assert.h>
36#include <iprt/err.h>
37#include <iprt/mem.h>
38#include <iprt/memsafer.h>
39#include <iprt/path.h>
40#include <iprt/string.h>
41#include <iprt/crypto/rsa.h>
42#include <iprt/crypto/pkix.h>
43#include <iprt/crypto/x509.h>
44
45#include "internal/magics.h"
46#include "key-internal.h"
47
48
49/*********************************************************************************************************************************
50* Header Files *
51*********************************************************************************************************************************/
52/** RSA public key marker words. */
53static RTCRPEMMARKERWORD const g_aWords_RsaPublicKey[] =
54{ { RT_STR_TUPLE("RSA") }, { RT_STR_TUPLE("PUBLIC") }, { RT_STR_TUPLE("KEY") } };
55/** Generic public key marker words. */
56static RTCRPEMMARKERWORD const g_aWords_PublicKey[] =
57{ { RT_STR_TUPLE("PUBLIC") }, { RT_STR_TUPLE("KEY") } };
58
59/** Public key markers. */
60RT_DECL_DATA_CONST(RTCRPEMMARKER const) g_aRTCrKeyPublicMarkers[] =
61{
62 { g_aWords_RsaPublicKey, RT_ELEMENTS(g_aWords_RsaPublicKey) },
63 { g_aWords_PublicKey, RT_ELEMENTS(g_aWords_PublicKey) },
64};
65/** Number of entries in g_aRTCrKeyPublicMarkers. */
66RT_DECL_DATA_CONST(uint32_t const) g_cRTCrKeyPublicMarkers = RT_ELEMENTS(g_aRTCrKeyPublicMarkers);
67
68
69/** RSA private key marker words. */
70static RTCRPEMMARKERWORD const g_aWords_RsaPrivateKey[] =
71{ { RT_STR_TUPLE("RSA") }, { RT_STR_TUPLE("PRIVATE") }, { RT_STR_TUPLE("KEY") } };
72/** Generic private key marker words. */
73static RTCRPEMMARKERWORD const g_aWords_PrivateKey[] =
74{ { RT_STR_TUPLE("PRIVATE") }, { RT_STR_TUPLE("KEY") } };
75
76/** Private key markers. */
77RT_DECL_DATA_CONST(RTCRPEMMARKER const) g_aRTCrKeyPrivateMarkers[] =
78{
79 { g_aWords_RsaPrivateKey, RT_ELEMENTS(g_aWords_RsaPrivateKey) },
80 { g_aWords_PrivateKey, RT_ELEMENTS(g_aWords_PrivateKey) },
81};
82/** Number of entries in g_aRTCrKeyPrivateMarkers. */
83RT_DECL_DATA_CONST(uint32_t const) g_cRTCrKeyPrivateMarkers = RT_ELEMENTS(g_aRTCrKeyPrivateMarkers);
84
85
86/** Private and public key markers. */
87RT_DECL_DATA_CONST(RTCRPEMMARKER const) g_aRTCrKeyAllMarkers[] =
88{
89 { g_aWords_RsaPublicKey, RT_ELEMENTS(g_aWords_RsaPublicKey) },
90 { g_aWords_PublicKey, RT_ELEMENTS(g_aWords_PublicKey) },
91 { g_aWords_RsaPrivateKey, RT_ELEMENTS(g_aWords_RsaPrivateKey) },
92 { g_aWords_PrivateKey, RT_ELEMENTS(g_aWords_PrivateKey) },
93};
94/** Number of entries in g_aRTCrKeyAllMarkers. */
95RT_DECL_DATA_CONST(uint32_t const) g_cRTCrKeyAllMarkers = RT_ELEMENTS(g_aRTCrKeyAllMarkers);
96
97
98
99RTDECL(int) RTCrKeyCreateFromPemSection(PRTCRKEY phKey, PCRTCRPEMSECTION pSection, uint32_t fFlags,
100 PRTERRINFO pErrInfo, const char *pszErrorTag)
101{
102 AssertReturn(!(fFlags & (~RTCRKEYFROM_F_VALID_MASK | RTCRKEYFROM_F_ONLY_PEM)), VERR_INVALID_FLAGS);
103
104 AssertPtrReturn(phKey, VERR_INVALID_POINTER);
105 *phKey = NIL_RTCRKEY;
106 AssertPtrReturn(pSection, VERR_INVALID_POINTER);
107
108 /*
109 * If the source is PEM section, try identify the format from the markers.
110 */
111 enum
112 {
113 kKeyFormat_Unknown = 0,
114 kKeyFormat_RsaPrivateKey,
115 kKeyFormat_RsaPublicKey,
116 kKeyFormat_PrivateKeyInfo,
117 kKeyFormat_SubjectPublicKeyInfo
118 } enmFormat = kKeyFormat_Unknown;
119 PCRTCRPEMMARKER pMarker = pSection->pMarker;
120 if (pMarker)
121 {
122 if ( pMarker->cWords == 3
123 && strcmp(pMarker->paWords[0].pszWord, "RSA") == 0
124 && strcmp(pMarker->paWords[2].pszWord, "KEY") == 0)
125 {
126 if (strcmp(pMarker->paWords[1].pszWord, "PUBLIC") == 0)
127 enmFormat = kKeyFormat_RsaPublicKey;
128 else if (strcmp(pMarker->paWords[1].pszWord, "PRIVATE") == 0)
129 enmFormat = kKeyFormat_RsaPrivateKey;
130 else
131 AssertFailed();
132 }
133 else if ( pMarker->cWords == 2
134 && strcmp(pMarker->paWords[1].pszWord, "KEY") == 0)
135 {
136 if (strcmp(pMarker->paWords[0].pszWord, "PUBLIC") == 0)
137 enmFormat = kKeyFormat_SubjectPublicKeyInfo;
138 else if (strcmp(pMarker->paWords[0].pszWord, "PRIVATE") == 0)
139 enmFormat = kKeyFormat_PrivateKeyInfo;
140 else
141 AssertFailed();
142 }
143 else
144 AssertFailed();
145 }
146
147 /*
148 * Try guess the format from the binary data if needed.
149 */
150 RTASN1CURSORPRIMARY PrimaryCursor;
151 if ( enmFormat == kKeyFormat_Unknown
152 && pSection->cbData > 10)
153 {
154 RTAsn1CursorInitPrimary(&PrimaryCursor, pSection->pbData, (uint32_t)pSection->cbData,
155 pErrInfo, &g_RTAsn1DefaultAllocator, RTASN1CURSOR_FLAGS_DER, "probing/0");
156
157 /*
158 * First the must be a sequence.
159 */
160 RTASN1CORE Tag;
161 int rc = RTAsn1CursorReadHdr(&PrimaryCursor.Cursor, &Tag, "#1");
162 if (RT_SUCCESS(rc) && Tag.uTag == ASN1_TAG_SEQUENCE)
163 {
164 RTASN1CURSOR Cursor2;
165 RTAsn1CursorInitSubFromCore(&PrimaryCursor.Cursor, &Tag, &Cursor2, "probing/1");
166 rc = RTAsn1CursorReadHdr(&Cursor2, &Tag, "#2");
167
168 /*
169 * SEQUENCE SubjectPublicKeyInfo.Algorithm?
170 */
171 if (RT_SUCCESS(rc) && Tag.uTag == ASN1_TAG_SEQUENCE)
172 {
173 RTASN1CURSOR Cursor3;
174 RTAsn1CursorInitSubFromCore(&Cursor2, &Tag, &Cursor3, "probing/2");
175 rc = RTAsn1CursorReadHdr(&Cursor3, &Tag, "#3");
176
177 /* SEQUENCE SubjectPublicKeyInfo.Algorithm.Algorithm? */
178 if (RT_SUCCESS(rc) && Tag.uTag == ASN1_TAG_OID)
179 enmFormat = kKeyFormat_SubjectPublicKeyInfo;
180 }
181 /*
182 * INTEGER PrivateKeyInfo.Version?
183 * INTEGER RsaPublicKey.Modulus?
184 * INTEGER RsaPrivateKey.Version?
185 */
186 else if (RT_SUCCESS(rc) && Tag.uTag == ASN1_TAG_INTEGER)
187 {
188 rc = RTAsn1CursorReadHdr(RTAsn1CursorSkip(&Cursor2, Tag.cb), &Tag, "#4");
189
190 /* OBJECT PrivateKeyInfo.privateKeyAlgorithm? */
191 if (RT_SUCCESS(rc) && Tag.uTag == ASN1_TAG_OID)
192 enmFormat = kKeyFormat_PrivateKeyInfo;
193 /* INTEGER RsaPublicKey.PublicExponent?
194 INTEGER RsaPrivateKey.Modulus? */
195 else if (RT_SUCCESS(rc) && Tag.uTag == ASN1_TAG_INTEGER)
196 {
197 /* RsaPublicKey.PublicExponent is at the end. */
198 if (RTAsn1CursorIsEnd(&Cursor2))
199 enmFormat = kKeyFormat_RsaPublicKey;
200 else
201 {
202 /* Check for INTEGER RsaPrivateKey.PublicExponent nad PrivateExponent before concluding. */
203 rc = RTAsn1CursorReadHdr(RTAsn1CursorSkip(&Cursor2, Tag.cb), &Tag, "#5");
204 if (RT_SUCCESS(rc) && Tag.uTag == ASN1_TAG_INTEGER)
205 {
206 rc = RTAsn1CursorReadHdr(RTAsn1CursorSkip(&Cursor2, Tag.cb), &Tag, "#6");
207 if (RT_SUCCESS(rc) && Tag.uTag == ASN1_TAG_INTEGER)
208 enmFormat = kKeyFormat_RsaPrivateKey;
209 }
210 }
211 }
212 }
213 }
214 }
215
216 if (enmFormat == kKeyFormat_Unknown)
217 return RTErrInfoSetF(pErrInfo, VERR_CR_KEY_UNKNOWN_TYPE,
218 "Unable to identify the key format (%.*Rhxs)", RT_MIN(16, pSection->cbData), pSection->pbData);
219
220 /*
221 * Do the reading.
222 */
223 int rc;
224 switch (enmFormat)
225 {
226 case kKeyFormat_RsaPrivateKey:
227 rc = rtCrKeyCreateRsaPrivate(phKey, pSection->pbData, (uint32_t)pSection->cbData, pErrInfo, pszErrorTag);
228 break;
229
230 case kKeyFormat_RsaPublicKey:
231 rc = rtCrKeyCreateRsaPrivate(phKey, pSection->pbData, (uint32_t)pSection->cbData, pErrInfo, pszErrorTag);
232 break;
233
234 case kKeyFormat_SubjectPublicKeyInfo:
235 {
236 RTAsn1CursorInitPrimary(&PrimaryCursor, pSection->pbData, (uint32_t)pSection->cbData,
237 pErrInfo, &g_RTAsn1DefaultAllocator, RTASN1CURSOR_FLAGS_DER, pszErrorTag);
238 RTCRX509SUBJECTPUBLICKEYINFO SubjectPubKeyInfo;
239 RT_ZERO(SubjectPubKeyInfo);
240 rc = RTCrX509SubjectPublicKeyInfo_DecodeAsn1(&PrimaryCursor.Cursor, 0, &SubjectPubKeyInfo, "SubjectPubKeyInfo");
241 if (RT_SUCCESS(rc))
242 {
243 rc = RTCrKeyCreateFromSubjectPublicKeyInfo(phKey, &SubjectPubKeyInfo, pErrInfo, pszErrorTag);
244 RTCrX509SubjectPublicKeyInfo_Delete(&SubjectPubKeyInfo);
245 }
246 break;
247 }
248
249 case kKeyFormat_PrivateKeyInfo:
250 rc = RTErrInfoSet(pErrInfo, VERR_CR_KEY_FORMAT_NOT_SUPPORTED,
251 "Support for PKCS#8 PrivateKeyInfo is not yet implemented");
252 break;
253
254 default:
255 AssertFailedStmt(rc = VERR_INTERNAL_ERROR_4);
256 }
257 return rc;
258}
259
260
261RTDECL(int) RTCrKeyCreateFromBuffer(PRTCRKEY phKey, uint32_t fFlags, void const *pvSrc, size_t cbSrc,
262 PRTERRINFO pErrInfo, const char *pszErrorTag)
263{
264 AssertReturn(!(fFlags & ~RTCRKEYFROM_F_VALID_MASK), VERR_INVALID_FLAGS);
265 PCRTCRPEMSECTION pSectionHead;
266 int rc = RTCrPemParseContent(pvSrc, cbSrc, fFlags, g_aRTCrKeyAllMarkers, g_cRTCrKeyAllMarkers, &pSectionHead, pErrInfo);
267 if (RT_SUCCESS(rc))
268 {
269 if (pSectionHead)
270 {
271 rc = RTCrKeyCreateFromPemSection(phKey, pSectionHead, fFlags & ~RTCRKEYFROM_F_ONLY_PEM, pErrInfo, pszErrorTag);
272 RTCrPemFreeSections(pSectionHead);
273 }
274 else
275 rc = rc != VINF_SUCCESS ? -rc : VERR_INTERNAL_ERROR_2;
276 }
277 return rc;
278}
279
280
281RTDECL(int) RTCrKeyCreateFromFile(PRTCRKEY phKey, uint32_t fFlags, const char *pszFilename, PRTERRINFO pErrInfo)
282{
283 AssertReturn(!(fFlags & ~RTCRKEYFROM_F_VALID_MASK), VERR_INVALID_FLAGS);
284 PCRTCRPEMSECTION pSectionHead;
285 int rc = RTCrPemReadFile(pszFilename, fFlags, g_aRTCrKeyAllMarkers, g_cRTCrKeyAllMarkers, &pSectionHead, pErrInfo);
286 if (RT_SUCCESS(rc))
287 {
288 if (pSectionHead)
289 {
290 rc = RTCrKeyCreateFromPemSection(phKey, pSectionHead, fFlags & ~RTCRKEYFROM_F_ONLY_PEM,
291 pErrInfo, RTPathFilename(pszFilename));
292 RTCrPemFreeSections(pSectionHead);
293 }
294 else
295 rc = rc != VINF_SUCCESS ? -rc : VERR_INTERNAL_ERROR_2;
296 }
297 return rc;
298}
299
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette