Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
pem.c
00001 /** 00002 * @file pem.c 00003 * @brief PEM (Privacy-Enhanced Mail) 00004 * 00005 * @section License 00006 * 00007 * Copyright (C) 2010-2017 Oryx Embedded SARL. All rights reserved. 00008 * 00009 * This file is part of CycloneCrypto Open. 00010 * 00011 * This program is free software; you can redistribute it and/or 00012 * modify it under the terms of the GNU General Public License 00013 * as published by the Free Software Foundation; either version 2 00014 * of the License, or (at your option) any later version. 00015 * 00016 * This program is distributed in the hope that it will be useful, 00017 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00019 * GNU General Public License for more details. 00020 * 00021 * You should have received a copy of the GNU General Public License 00022 * along with this program; if not, write to the Free Software Foundation, 00023 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00024 * 00025 * @author Oryx Embedded SARL (www.oryx-embedded.com) 00026 * @version 1.7.6 00027 **/ 00028 00029 //Switch to the appropriate trace level 00030 #define TRACE_LEVEL CRYPTO_TRACE_LEVEL 00031 00032 //Dependencies 00033 #include <string.h> 00034 #include "crypto.h" 00035 #include "pem.h" 00036 #include "asn1.h" 00037 #include "base64.h" 00038 #include "mpi.h" 00039 #include "debug.h" 00040 00041 //Check crypto library configuration 00042 #if (PEM_SUPPORT == ENABLED) 00043 00044 00045 /** 00046 * @brief Decode a PEM file containing Diffie-Hellman parameters 00047 * @param[in] input Pointer to the PEM structure 00048 * @param[in] length Length of the PEM structure 00049 * @param[out] params Diffie-Hellman parameters resulting from the parsing process 00050 * @return Error code 00051 **/ 00052 00053 error_t pemReadDhParameters(const char_t *input, size_t length, DhParameters *params) 00054 { 00055 #if (DH_SUPPORT == ENABLED) 00056 error_t error; 00057 size_t i; 00058 size_t j; 00059 int_t k; 00060 char_t *buffer; 00061 const uint8_t *data; 00062 Asn1Tag tag; 00063 00064 //Check parameters 00065 if(input == NULL && length != 0) 00066 return ERROR_INVALID_PARAMETER; 00067 if(params == NULL) 00068 return ERROR_INVALID_PARAMETER; 00069 00070 //Search for the beginning tag 00071 k = pemSearchTag(input, length, "-----BEGIN DH PARAMETERS-----", 29); 00072 //Failed to find the specified tag? 00073 if(k < 0) 00074 return ERROR_INVALID_SYNTAX; 00075 00076 //Advance the pointer over the tag 00077 input += k + 29; 00078 length -= k + 29; 00079 00080 //Search for the end tag 00081 k = pemSearchTag(input, length, "-----END DH PARAMETERS-----", 27); 00082 //Invalid PEM file? 00083 if(k <= 0) 00084 return ERROR_INVALID_SYNTAX; 00085 00086 //Length of the PEM structure 00087 length = k; 00088 00089 //Allocate a memory buffer to hold the decoded data 00090 buffer = cryptoAllocMem(length); 00091 //Failed to allocate memory? 00092 if(buffer == NULL) 00093 return ERROR_OUT_OF_MEMORY; 00094 00095 //Copy the contents of the PEM structure 00096 memcpy(buffer, input, length); 00097 00098 //Remove carriage returns and line feeds 00099 for(i = 0, j = 0; i < length; i++) 00100 { 00101 if(buffer[i] != '\r' && buffer[i] != '\n') 00102 buffer[j++] = buffer[i]; 00103 } 00104 00105 //Start of exception handling block 00106 do 00107 { 00108 //The PEM file is Base64 encoded... 00109 error = base64Decode(buffer, j, buffer, &length); 00110 //Failed to decode the file? 00111 if(error) 00112 break; 00113 00114 //Point to the resulting ASN.1 structure 00115 data = (uint8_t *) buffer; 00116 00117 //Display ASN.1 structure 00118 error = asn1DumpObject(data, length, 0); 00119 //Any error to report? 00120 if(error) 00121 break; 00122 00123 //The Diffie-Hellman parameters are encapsulated within a sequence 00124 error = asn1ReadTag(data, length, &tag); 00125 //Failed to decode ASN.1 tag? 00126 if(error) 00127 break; 00128 00129 //Enforce encoding, class and type 00130 error = asn1CheckTag(&tag, TRUE, ASN1_CLASS_UNIVERSAL, ASN1_TYPE_SEQUENCE); 00131 //The tag does not match the criteria? 00132 if(error) 00133 break; 00134 00135 //Point to the first field of the sequence 00136 data = tag.value; 00137 length = tag.length; 00138 00139 //Read the prime modulus 00140 error = asn1ReadTag(data, length, &tag); 00141 //Failed to decode ASN.1 tag? 00142 if(error) 00143 break; 00144 00145 //Enforce encoding, class and type 00146 error = asn1CheckTag(&tag, FALSE, ASN1_CLASS_UNIVERSAL, ASN1_TYPE_INTEGER); 00147 //The tag does not match the criteria? 00148 if(error) 00149 break; 00150 00151 //Convert the prime modulus to a multiple precision integer 00152 error = mpiReadRaw(¶ms->p, tag.value, tag.length); 00153 //Any error to report? 00154 if(error) 00155 break; 00156 00157 //Point to the next field 00158 data += tag.totalLength; 00159 length -= tag.totalLength; 00160 00161 //Read the generator 00162 error = asn1ReadTag(data, length, &tag); 00163 //Failed to decode ASN.1 tag? 00164 if(error) 00165 break; 00166 00167 //Enforce encoding, class and type 00168 error = asn1CheckTag(&tag, FALSE, ASN1_CLASS_UNIVERSAL, ASN1_TYPE_INTEGER); 00169 //The tag does not match the criteria? 00170 if(error) 00171 break; 00172 00173 //Convert the generator to a multiple precision integer 00174 error = mpiReadRaw(¶ms->g, tag.value, tag.length); 00175 //Any error to report? 00176 if(error) 00177 break; 00178 00179 //Debug message 00180 TRACE_DEBUG("Diffie-Hellman parameters:\r\n"); 00181 TRACE_DEBUG(" Prime modulus:\r\n"); 00182 TRACE_DEBUG_MPI(" ", ¶ms->p); 00183 TRACE_DEBUG(" Generator:\r\n"); 00184 TRACE_DEBUG_MPI(" ", ¶ms->g); 00185 00186 //End of exception handling block 00187 } while(0); 00188 00189 //Release previously allocated memory 00190 cryptoFreeMem(buffer); 00191 00192 //Any error to report? 00193 if(error) 00194 { 00195 //Clean up side effects 00196 mpiFree(¶ms->p); 00197 mpiFree(¶ms->g); 00198 } 00199 00200 //Return status code 00201 return error; 00202 #else 00203 //Not implemented 00204 return ERROR_NOT_IMPLEMENTED; 00205 #endif 00206 } 00207 00208 00209 /** 00210 * @brief Decode a PEM file containing a RSA private key 00211 * @param[in] input Pointer to the PEM structure 00212 * @param[in] length Length of the PEM structure 00213 * @param[out] key RSA private key resulting from the parsing process 00214 * @return Error code 00215 **/ 00216 00217 error_t pemReadRsaPrivateKey(const char_t *input, size_t length, RsaPrivateKey *key) 00218 { 00219 #if (RSA_SUPPORT == ENABLED) 00220 error_t error; 00221 size_t i; 00222 size_t j; 00223 int_t k; 00224 char_t *buffer; 00225 const uint8_t *data; 00226 Asn1Tag tag; 00227 00228 //Check parameters 00229 if(input == NULL && length != 0) 00230 return ERROR_INVALID_PARAMETER; 00231 if(key == NULL) 00232 return ERROR_INVALID_PARAMETER; 00233 00234 //Search for the beginning tag 00235 k = pemSearchTag(input, length, "-----BEGIN RSA PRIVATE KEY-----", 31); 00236 //Failed to find the specified tag? 00237 if(k < 0) 00238 return ERROR_INVALID_SYNTAX; 00239 00240 //Advance the pointer over the tag 00241 input += k + 31; 00242 length -= k + 31; 00243 00244 //Search for the end tag 00245 k = pemSearchTag(input, length, "-----END RSA PRIVATE KEY-----", 29); 00246 //Invalid PEM file? 00247 if(k <= 0) 00248 return ERROR_INVALID_SYNTAX; 00249 00250 //Length of the PEM structure 00251 length = k; 00252 00253 //Allocate a memory buffer to hold the decoded data 00254 buffer = cryptoAllocMem(length); 00255 //Failed to allocate memory? 00256 if(buffer == NULL) 00257 return ERROR_OUT_OF_MEMORY; 00258 00259 //Copy the contents of the PEM structure 00260 memcpy(buffer, input, length); 00261 00262 //Remove carriage returns and line feeds 00263 for(i = 0, j = 0; i < length; i++) 00264 { 00265 if(buffer[i] != '\r' && buffer[i] != '\n') 00266 buffer[j++] = buffer[i]; 00267 } 00268 00269 //Start of exception handling block 00270 do 00271 { 00272 //The PEM file is Base64 encoded... 00273 error = base64Decode(buffer, j, buffer, &length); 00274 //Failed to decode the file? 00275 if(error) 00276 break; 00277 00278 //Point to the resulting ASN.1 structure 00279 data = (uint8_t *) buffer; 00280 00281 //Display ASN.1 structure 00282 error = asn1DumpObject(data, length, 0); 00283 //Any error to report? 00284 if(error) 00285 break; 00286 00287 //The RSA private key is encapsulated within a sequence 00288 error = asn1ReadTag(data, length, &tag); 00289 //Failed to decode ASN.1 tag? 00290 if(error) 00291 break; 00292 00293 //Enforce encoding, class and type 00294 error = asn1CheckTag(&tag, TRUE, ASN1_CLASS_UNIVERSAL, ASN1_TYPE_SEQUENCE); 00295 //The tag does not match the criteria? 00296 if(error) 00297 break; 00298 00299 //Point to the first field of the sequence 00300 data = tag.value; 00301 length = tag.length; 00302 00303 //Read the version 00304 error = asn1ReadTag(data, length, &tag); 00305 //Failed to decode ASN.1 tag? 00306 if(error) 00307 break; 00308 00309 //Enforce encoding, class and type 00310 error = asn1CheckTag(&tag, FALSE, ASN1_CLASS_UNIVERSAL, ASN1_TYPE_INTEGER); 00311 //The tag does not match the criteria? 00312 if(error) 00313 break; 00314 00315 //Skip the version field 00316 data += tag.totalLength; 00317 length -= tag.totalLength; 00318 00319 //Read the modulus 00320 error = asn1ReadTag(data, length, &tag); 00321 //Failed to decode ASN.1 tag? 00322 if(error) 00323 break; 00324 00325 //Enforce encoding, class and type 00326 error = asn1CheckTag(&tag, FALSE, ASN1_CLASS_UNIVERSAL, ASN1_TYPE_INTEGER); 00327 //The tag does not match the criteria? 00328 if(error) 00329 break; 00330 00331 //Convert the modulus to a multiple precision integer 00332 error = mpiReadRaw(&key->n, tag.value, tag.length); 00333 //Any error to report? 00334 if(error) 00335 break; 00336 00337 //Point to the next field 00338 data += tag.totalLength; 00339 length -= tag.totalLength; 00340 00341 //Read the public exponent 00342 error = asn1ReadTag(data, length, &tag); 00343 //Failed to decode ASN.1 tag? 00344 if(error) 00345 break; 00346 00347 //Enforce encoding, class and type 00348 error = asn1CheckTag(&tag, FALSE, ASN1_CLASS_UNIVERSAL, ASN1_TYPE_INTEGER); 00349 //The tag does not match the criteria? 00350 if(error) 00351 break; 00352 00353 //Convert the public exponent to a multiple precision integer 00354 error = mpiReadRaw(&key->e, tag.value, tag.length); 00355 //Any error to report? 00356 if(error) 00357 break; 00358 00359 //Point to the next field 00360 data += tag.totalLength; 00361 length -= tag.totalLength; 00362 00363 //Read the private exponent 00364 error = asn1ReadTag(data, length, &tag); 00365 //Failed to decode ASN.1 tag? 00366 if(error) 00367 break; 00368 00369 //Enforce encoding, class and type 00370 error = asn1CheckTag(&tag, FALSE, ASN1_CLASS_UNIVERSAL, ASN1_TYPE_INTEGER); 00371 //The tag does not match the criteria? 00372 if(error) 00373 break; 00374 00375 //Convert the private exponent to a multiple precision integer 00376 error = mpiReadRaw(&key->d, tag.value, tag.length); 00377 //Any error to report? 00378 if(error) 00379 break; 00380 00381 //Point to the next field 00382 data += tag.totalLength; 00383 length -= tag.totalLength; 00384 00385 //Read the first factor 00386 error = asn1ReadTag(data, length, &tag); 00387 //Failed to decode ASN.1 tag? 00388 if(error) 00389 break; 00390 00391 //Enforce encoding, class and type 00392 error = asn1CheckTag(&tag, FALSE, ASN1_CLASS_UNIVERSAL, ASN1_TYPE_INTEGER); 00393 //The tag does not match the criteria? 00394 if(error) 00395 break; 00396 00397 //Convert the first factor to a multiple precision integer 00398 error = mpiReadRaw(&key->p, tag.value, tag.length); 00399 //Any error to report? 00400 if(error) 00401 break; 00402 00403 //Point to the next field 00404 data += tag.totalLength; 00405 length -= tag.totalLength; 00406 00407 //Read the second factor 00408 error = asn1ReadTag(data, length, &tag); 00409 //Failed to decode ASN.1 tag? 00410 if(error) 00411 break; 00412 00413 //Enforce encoding, class and type 00414 error = asn1CheckTag(&tag, FALSE, ASN1_CLASS_UNIVERSAL, ASN1_TYPE_INTEGER); 00415 //The tag does not match the criteria? 00416 if(error) 00417 break; 00418 00419 //Convert the second factor to a multiple precision integer 00420 error = mpiReadRaw(&key->q, tag.value, tag.length); 00421 //Any error to report? 00422 if(error) 00423 break; 00424 00425 //Point to the next field 00426 data += tag.totalLength; 00427 length -= tag.totalLength; 00428 00429 //Read the first exponent 00430 error = asn1ReadTag(data, length, &tag); 00431 //Failed to decode ASN.1 tag? 00432 if(error) 00433 break; 00434 00435 //Enforce encoding, class and type 00436 error = asn1CheckTag(&tag, FALSE, ASN1_CLASS_UNIVERSAL, ASN1_TYPE_INTEGER); 00437 //The tag does not match the criteria? 00438 if(error) 00439 break; 00440 00441 //Convert the first exponent to a multiple precision integer 00442 error = mpiReadRaw(&key->dp, tag.value, tag.length); 00443 //Any error to report? 00444 if(error) 00445 break; 00446 00447 //Point to the next field 00448 data += tag.totalLength; 00449 length -= tag.totalLength; 00450 00451 //Read the second exponent 00452 error = asn1ReadTag(data, length, &tag); 00453 //Failed to decode ASN.1 tag? 00454 if(error) 00455 break; 00456 00457 //Enforce encoding, class and type 00458 error = asn1CheckTag(&tag, FALSE, ASN1_CLASS_UNIVERSAL, ASN1_TYPE_INTEGER); 00459 //The tag does not match the criteria? 00460 if(error) 00461 break; 00462 00463 //Convert the second exponent to a multiple precision integer 00464 error = mpiReadRaw(&key->dq, tag.value, tag.length); 00465 //Any error to report? 00466 if(error) 00467 break; 00468 00469 //Point to the next field 00470 data += tag.totalLength; 00471 length -= tag.totalLength; 00472 00473 //Read the coefficient 00474 error = asn1ReadTag(data, length, &tag); 00475 //Failed to decode ASN.1 tag? 00476 if(error) 00477 break; 00478 00479 //Enforce encoding, class and type 00480 error = asn1CheckTag(&tag, FALSE, ASN1_CLASS_UNIVERSAL, ASN1_TYPE_INTEGER); 00481 //The tag does not match the criteria? 00482 if(error) 00483 break; 00484 00485 //Convert the coefficient to a multiple precision integer 00486 error = mpiReadRaw(&key->qinv, tag.value, tag.length); 00487 //Any error to report? 00488 if(error) 00489 break; 00490 00491 //Debug message 00492 TRACE_DEBUG("RSA private key:\r\n"); 00493 TRACE_DEBUG(" Modulus:\r\n"); 00494 TRACE_DEBUG_MPI(" ", &key->n); 00495 TRACE_DEBUG(" Public exponent:\r\n"); 00496 TRACE_DEBUG_MPI(" ", &key->e); 00497 TRACE_DEBUG(" Private exponent:\r\n"); 00498 TRACE_DEBUG_MPI(" ", &key->d); 00499 TRACE_DEBUG(" Prime 1:\r\n"); 00500 TRACE_DEBUG_MPI(" ", &key->p); 00501 TRACE_DEBUG(" Prime 2:\r\n"); 00502 TRACE_DEBUG_MPI(" ", &key->q); 00503 TRACE_DEBUG(" Prime exponent 1:\r\n"); 00504 TRACE_DEBUG_MPI(" ", &key->dp); 00505 TRACE_DEBUG(" Prime exponent 2:\r\n"); 00506 TRACE_DEBUG_MPI(" ", &key->dq); 00507 TRACE_DEBUG(" Coefficient:\r\n"); 00508 TRACE_DEBUG_MPI(" ", &key->qinv); 00509 00510 //End of exception handling block 00511 } while(0); 00512 00513 //Release previously allocated memory 00514 cryptoFreeMem(buffer); 00515 00516 //Clean up side effects if necessary 00517 if(error) 00518 rsaFreePrivateKey(key); 00519 00520 //Return status code 00521 return error; 00522 #else 00523 //Not implemented 00524 return ERROR_NOT_IMPLEMENTED; 00525 #endif 00526 } 00527 00528 00529 /** 00530 * @brief Decode a PEM file containing a DSA private key 00531 * @param[in] input Pointer to the PEM structure 00532 * @param[in] length Length of the PEM structure 00533 * @param[out] key DSA private key resulting from the parsing process 00534 * @return Error code 00535 **/ 00536 00537 error_t pemReadDsaPrivateKey(const char_t *input, size_t length, DsaPrivateKey *key) 00538 { 00539 #if (DSA_SUPPORT == ENABLED) 00540 error_t error; 00541 size_t i; 00542 size_t j; 00543 int_t k; 00544 char_t *buffer; 00545 const uint8_t *data; 00546 Asn1Tag tag; 00547 00548 //Check parameters 00549 if(input == NULL && length != 0) 00550 return ERROR_INVALID_PARAMETER; 00551 if(key == NULL) 00552 return ERROR_INVALID_PARAMETER; 00553 00554 //Search for the beginning tag 00555 k = pemSearchTag(input, length, "-----BEGIN DSA PRIVATE KEY-----", 31); 00556 //Failed to find the specified tag? 00557 if(k < 0) 00558 return ERROR_INVALID_SYNTAX; 00559 00560 //Advance the pointer over the tag 00561 input += k + 31; 00562 length -= k + 31; 00563 00564 //Search for the end tag 00565 k = pemSearchTag(input, length, "-----END DSA PRIVATE KEY-----", 29); 00566 //Invalid PEM file? 00567 if(k <= 0) 00568 return ERROR_INVALID_SYNTAX; 00569 00570 //Length of the PEM structure 00571 length = k; 00572 00573 //Allocate a memory buffer to hold the decoded data 00574 buffer = cryptoAllocMem(length); 00575 //Failed to allocate memory? 00576 if(buffer == NULL) 00577 return ERROR_OUT_OF_MEMORY; 00578 00579 //Copy the contents of the PEM structure 00580 memcpy(buffer, input, length); 00581 00582 //Remove carriage returns and line feeds 00583 for(i = 0, j = 0; i < length; i++) 00584 { 00585 if(buffer[i] != '\r' && buffer[i] != '\n') 00586 buffer[j++] = buffer[i]; 00587 } 00588 00589 //Start of exception handling block 00590 do 00591 { 00592 //The PEM file is Base64 encoded... 00593 error = base64Decode(buffer, j, buffer, &length); 00594 //Failed to decode the file? 00595 if(error) 00596 break; 00597 00598 //Point to the resulting ASN.1 structure 00599 data = (uint8_t *) buffer; 00600 00601 //Display ASN.1 structure 00602 error = asn1DumpObject(data, length, 0); 00603 //Any error to report? 00604 if(error) 00605 break; 00606 00607 //The DSA private key is encapsulated within a sequence 00608 error = asn1ReadTag(data, length, &tag); 00609 //Failed to decode ASN.1 tag? 00610 if(error) 00611 break; 00612 00613 //Enforce encoding, class and type 00614 error = asn1CheckTag(&tag, TRUE, ASN1_CLASS_UNIVERSAL, ASN1_TYPE_SEQUENCE); 00615 //The tag does not match the criteria? 00616 if(error) 00617 break; 00618 00619 //Point to the first field of the sequence 00620 data = tag.value; 00621 length = tag.length; 00622 00623 //Read the version 00624 error = asn1ReadTag(data, length, &tag); 00625 //Failed to decode ASN.1 tag? 00626 if(error) 00627 break; 00628 00629 //Enforce encoding, class and type 00630 error = asn1CheckTag(&tag, FALSE, ASN1_CLASS_UNIVERSAL, ASN1_TYPE_INTEGER); 00631 //The tag does not match the criteria? 00632 if(error) 00633 break; 00634 00635 //Skip the version field 00636 data += tag.totalLength; 00637 length -= tag.totalLength; 00638 00639 //Read p 00640 error = asn1ReadTag(data, length, &tag); 00641 //Failed to decode ASN.1 tag? 00642 if(error) 00643 break; 00644 00645 //Enforce encoding, class and type 00646 error = asn1CheckTag(&tag, FALSE, ASN1_CLASS_UNIVERSAL, ASN1_TYPE_INTEGER); 00647 //The tag does not match the criteria? 00648 if(error) 00649 break; 00650 00651 //Convert p to a multiple precision integer 00652 error = mpiReadRaw(&key->p, tag.value, tag.length); 00653 //Any error to report? 00654 if(error) 00655 break; 00656 00657 //Point to the next field 00658 data += tag.totalLength; 00659 length -= tag.totalLength; 00660 00661 //Read q 00662 error = asn1ReadTag(data, length, &tag); 00663 //Failed to decode ASN.1 tag? 00664 if(error) 00665 break; 00666 00667 //Enforce encoding, class and type 00668 error = asn1CheckTag(&tag, FALSE, ASN1_CLASS_UNIVERSAL, ASN1_TYPE_INTEGER); 00669 //The tag does not match the criteria? 00670 if(error) 00671 break; 00672 00673 //Convert q to a multiple precision integer 00674 error = mpiReadRaw(&key->q, tag.value, tag.length); 00675 //Any error to report? 00676 if(error) 00677 break; 00678 00679 //Point to the next field 00680 data += tag.totalLength; 00681 length -= tag.totalLength; 00682 00683 //Read g 00684 error = asn1ReadTag(data, length, &tag); 00685 //Failed to decode ASN.1 tag? 00686 if(error) 00687 break; 00688 00689 //Enforce encoding, class and type 00690 error = asn1CheckTag(&tag, FALSE, ASN1_CLASS_UNIVERSAL, ASN1_TYPE_INTEGER); 00691 //The tag does not match the criteria? 00692 if(error) 00693 break; 00694 00695 //Convert g to a multiple precision integer 00696 error = mpiReadRaw(&key->g, tag.value, tag.length); 00697 //Any error to report? 00698 if(error) 00699 break; 00700 00701 //Point to the next field 00702 data += tag.totalLength; 00703 length -= tag.totalLength; 00704 00705 //Read the public value 00706 error = asn1ReadTag(data, length, &tag); 00707 //Failed to decode ASN.1 tag? 00708 if(error) 00709 break; 00710 00711 //Enforce encoding, class and type 00712 error = asn1CheckTag(&tag, FALSE, ASN1_CLASS_UNIVERSAL, ASN1_TYPE_INTEGER); 00713 //The tag does not match the criteria? 00714 if(error) 00715 break; 00716 00717 //Point to the next field 00718 data += tag.totalLength; 00719 length -= tag.totalLength; 00720 00721 //Read the private value 00722 error = asn1ReadTag(data, length, &tag); 00723 //Failed to decode ASN.1 tag? 00724 if(error) 00725 break; 00726 00727 //Enforce encoding, class and type 00728 error = asn1CheckTag(&tag, FALSE, ASN1_CLASS_UNIVERSAL, ASN1_TYPE_INTEGER); 00729 //The tag does not match the criteria? 00730 if(error) 00731 break; 00732 00733 //Convert the private value to a multiple precision integer 00734 error = mpiReadRaw(&key->x, tag.value, tag.length); 00735 //Any error to report? 00736 if(error) 00737 break; 00738 00739 //Debug message 00740 TRACE_DEBUG("DSA private key:\r\n"); 00741 TRACE_DEBUG(" p:\r\n"); 00742 TRACE_DEBUG_MPI(" ", &key->p); 00743 TRACE_DEBUG(" q:\r\n"); 00744 TRACE_DEBUG_MPI(" ", &key->q); 00745 TRACE_DEBUG(" g:\r\n"); 00746 TRACE_DEBUG_MPI(" ", &key->g); 00747 TRACE_DEBUG(" x:\r\n"); 00748 TRACE_DEBUG_MPI(" ", &key->x); 00749 00750 //End of exception handling block 00751 } while(0); 00752 00753 //Release previously allocated memory 00754 cryptoFreeMem(buffer); 00755 00756 //Clean up side effects if necessary 00757 if(error) 00758 dsaFreePrivateKey(key); 00759 00760 //Return status code 00761 return error; 00762 #else 00763 //Not implemented 00764 return ERROR_NOT_IMPLEMENTED; 00765 #endif 00766 } 00767 00768 00769 /** 00770 * @brief Decode a PEM file containing EC domain parameters 00771 * @param[in] input Pointer to the PEM structure 00772 * @param[in] length Length of the PEM structure 00773 * @param[out] params EC domain parameters 00774 * @return Error code 00775 **/ 00776 00777 error_t pemReadEcParameters(const char_t *input, size_t length, EcDomainParameters *params) 00778 { 00779 #if (EC_SUPPORT == ENABLED) 00780 error_t error; 00781 size_t i; 00782 size_t j; 00783 int_t k; 00784 char_t *buffer; 00785 const uint8_t *data; 00786 Asn1Tag tag; 00787 const EcCurveInfo *curveInfo; 00788 00789 //Check parameters 00790 if(input == NULL && length != 0) 00791 return ERROR_INVALID_PARAMETER; 00792 if(params == NULL) 00793 return ERROR_INVALID_PARAMETER; 00794 00795 //Check the format of the PEM file 00796 if(pemSearchTag(input, length, "-----BEGIN EC PARAMETERS-----", 29) >= 0) 00797 { 00798 //Search for the beginning tag 00799 k = pemSearchTag(input, length, "-----BEGIN EC PARAMETERS-----", 29); 00800 //Failed to find the specified tag? 00801 if(k < 0) 00802 return ERROR_INVALID_SYNTAX; 00803 00804 //Advance the pointer over the tag 00805 input += k + 29; 00806 length -= k + 29; 00807 00808 //Search for the end tag 00809 k = pemSearchTag(input, length, "-----END EC PARAMETERS-----", 27); 00810 //Invalid PEM file? 00811 if(k <= 0) 00812 return ERROR_INVALID_SYNTAX; 00813 00814 //Length of the PEM structure 00815 length = k; 00816 00817 //Allocate a memory buffer to hold the decoded data 00818 buffer = cryptoAllocMem(length); 00819 //Failed to allocate memory? 00820 if(buffer == NULL) 00821 return ERROR_OUT_OF_MEMORY; 00822 00823 //Copy the contents of the PEM structure 00824 memcpy(buffer, input, length); 00825 00826 //Remove carriage returns and line feeds 00827 for(i = 0, j = 0; i < length; i++) 00828 { 00829 if(buffer[i] != '\r' && buffer[i] != '\n') 00830 buffer[j++] = buffer[i]; 00831 } 00832 00833 //Start of exception handling block 00834 do 00835 { 00836 //The PEM file is Base64 encoded... 00837 error = base64Decode(buffer, j, buffer, &length); 00838 //Failed to decode the file? 00839 if(error) 00840 break; 00841 00842 //Point to the resulting ASN.1 structure 00843 data = (uint8_t *) buffer; 00844 00845 //Display ASN.1 structure 00846 error = asn1DumpObject(data, length, 0); 00847 //Any error to report? 00848 if(error) 00849 break; 00850 00851 //Read the curve identifier 00852 error = asn1ReadTag(data, length, &tag); 00853 //Failed to decode ASN.1 tag? 00854 if(error) 00855 break; 00856 00857 //Enforce encoding, class and type 00858 error = asn1CheckTag(&tag, FALSE, ASN1_CLASS_UNIVERSAL, ASN1_TYPE_OBJECT_IDENTIFIER); 00859 //The tag does not match the criteria? 00860 if(error) 00861 break; 00862 00863 //Retrieve EC domain parameters 00864 curveInfo = ecGetCurveInfo(tag.value, tag.length); 00865 //Make sure the specified elliptic curve is supported 00866 if(curveInfo == NULL) 00867 { 00868 //Report an error 00869 error = ERROR_ILLEGAL_PARAMETER; 00870 //Exit immediately 00871 break; 00872 } 00873 00874 //Load EC domain parameters 00875 error = ecLoadDomainParameters(params, curveInfo); 00876 //Any error to report? 00877 if(error) 00878 break; 00879 00880 //End of exception handling block 00881 } while(0); 00882 } 00883 else 00884 { 00885 //Search for the beginning tag 00886 k = pemSearchTag(input, length, "-----BEGIN PRIVATE KEY-----", 27); 00887 //Failed to find the specified tag? 00888 if(k < 0) 00889 return ERROR_INVALID_SYNTAX; 00890 00891 //Advance the pointer over the tag 00892 input += k + 27; 00893 length -= k + 27; 00894 00895 //Search for the end tag 00896 k = pemSearchTag(input, length, "-----END PRIVATE KEY-----", 25); 00897 //Invalid PEM file? 00898 if(k <= 0) 00899 return ERROR_INVALID_SYNTAX; 00900 00901 //Length of the PEM structure 00902 length = k; 00903 00904 //Allocate a memory buffer to hold the decoded data 00905 buffer = cryptoAllocMem(length); 00906 //Failed to allocate memory? 00907 if(buffer == NULL) 00908 return ERROR_OUT_OF_MEMORY; 00909 00910 //Copy the contents of the PEM structure 00911 memcpy(buffer, input, length); 00912 00913 //Remove carriage returns and line feeds 00914 for(i = 0, j = 0; i < length; i++) 00915 { 00916 if(buffer[i] != '\r' && buffer[i] != '\n') 00917 buffer[j++] = buffer[i]; 00918 } 00919 00920 //Start of exception handling block 00921 do 00922 { 00923 //The PEM file is Base64 encoded... 00924 error = base64Decode(buffer, j, buffer, &length); 00925 //Failed to decode the file? 00926 if(error) 00927 break; 00928 00929 //Point to the resulting ASN.1 structure 00930 data = (uint8_t *) buffer; 00931 00932 //Display ASN.1 structure 00933 error = asn1DumpObject(data, length, 0); 00934 //Any error to report? 00935 if(error) 00936 break; 00937 00938 //The private key is encapsulated within a sequence 00939 error = asn1ReadTag(data, length, &tag); 00940 //Failed to decode ASN.1 tag? 00941 if(error) 00942 break; 00943 00944 //Enforce encoding, class and type 00945 error = asn1CheckTag(&tag, TRUE, ASN1_CLASS_UNIVERSAL, ASN1_TYPE_SEQUENCE); 00946 //The tag does not match the criteria? 00947 if(error) 00948 break; 00949 00950 //Point to the first field of the sequence 00951 data = tag.value; 00952 length = tag.length; 00953 00954 //Read the Version field 00955 error = asn1ReadTag(data, length, &tag); 00956 //Failed to decode ASN.1 tag? 00957 if(error) 00958 break; 00959 00960 //Enforce encoding, class and type 00961 error = asn1CheckTag(&tag, FALSE, ASN1_CLASS_UNIVERSAL, ASN1_TYPE_INTEGER); 00962 //The tag does not match the criteria? 00963 if(error) 00964 break; 00965 00966 //Skip the Version field 00967 data += tag.totalLength; 00968 length -= tag.totalLength; 00969 00970 //Read the PrivateKeyAlgorithmIdentifier field 00971 error = asn1ReadTag(data, length, &tag); 00972 //Failed to decode ASN.1 tag? 00973 if(error) 00974 break; 00975 00976 //Enforce encoding, class and type 00977 error = asn1CheckTag(&tag, TRUE, ASN1_CLASS_UNIVERSAL, ASN1_TYPE_SEQUENCE); 00978 //The tag does not match the criteria? 00979 if(error) 00980 break; 00981 00982 //Point to the first field of the sequence 00983 data = tag.value; 00984 length = tag.length; 00985 00986 //Read the algorithm identifier (OID) 00987 error = asn1ReadTag(data, length, &tag); 00988 //Failed to decode ASN.1 tag? 00989 if(error) 00990 break; 00991 00992 //Check algorithm identifier 00993 error = asn1CheckOid(&tag, EC_PUBLIC_KEY_OID, sizeof(EC_PUBLIC_KEY_OID)); 00994 //Wrong identifier? 00995 if(error) 00996 break; 00997 00998 //Point to the next field 00999 data += tag.totalLength; 01000 length += tag.totalLength; 01001 01002 //Read namedCurve field 01003 error = asn1ReadTag(data, length, &tag); 01004 //Failed to decode ASN.1 tag? 01005 if(error) 01006 break; 01007 01008 //Enforce encoding, class and type 01009 error = asn1CheckTag(&tag, FALSE, ASN1_CLASS_UNIVERSAL, ASN1_TYPE_OBJECT_IDENTIFIER); 01010 //The tag does not match the criteria? 01011 if(error) 01012 break; 01013 01014 //Retrieve EC domain parameters 01015 curveInfo = ecGetCurveInfo(tag.value, tag.length); 01016 //Make sure the specified elliptic curve is supported 01017 if(curveInfo == NULL) 01018 { 01019 //Report an error 01020 error = ERROR_ILLEGAL_PARAMETER; 01021 //Exit immediately 01022 break; 01023 } 01024 01025 //Load EC domain parameters 01026 error = ecLoadDomainParameters(params, curveInfo); 01027 //Any error to report? 01028 if(error) 01029 break; 01030 01031 //End of exception handling block 01032 } while(0); 01033 } 01034 01035 //Release previously allocated memory 01036 cryptoFreeMem(buffer); 01037 01038 //Clean up side effects if necessary 01039 if(error) 01040 ecFreeDomainParameters(params); 01041 01042 //Return status code 01043 return error; 01044 #else 01045 //Not implemented 01046 return ERROR_NOT_IMPLEMENTED; 01047 #endif 01048 } 01049 01050 01051 /** 01052 * @brief Decode a PEM file containing an EC private key 01053 * @param[in] input Pointer to the PEM structure 01054 * @param[in] length Length of the PEM structure 01055 * @param[out] key EC private key resulting from the parsing process 01056 * @return Error code 01057 **/ 01058 01059 error_t pemReadEcPrivateKey(const char_t *input, size_t length, Mpi *key) 01060 { 01061 #if (EC_SUPPORT == ENABLED) 01062 error_t error; 01063 size_t i; 01064 size_t j; 01065 int_t k; 01066 char_t *buffer; 01067 const uint8_t *data; 01068 Asn1Tag tag; 01069 01070 //Check parameters 01071 if(input == NULL && length != 0) 01072 return ERROR_INVALID_PARAMETER; 01073 if(key == NULL) 01074 return ERROR_INVALID_PARAMETER; 01075 01076 //Check the format of the PEM file 01077 if(pemSearchTag(input, length, "-----BEGIN EC PRIVATE KEY-----", 30) >= 0) 01078 { 01079 //Search for the beginning tag 01080 k = pemSearchTag(input, length, "-----BEGIN EC PRIVATE KEY-----", 30); 01081 //Failed to find the specified tag? 01082 if(k < 0) 01083 return ERROR_INVALID_SYNTAX; 01084 01085 //Advance the pointer over the tag 01086 input += k + 30; 01087 length -= k + 30; 01088 01089 //Search for the end tag 01090 k = pemSearchTag(input, length, "-----END EC PRIVATE KEY-----", 28); 01091 //Invalid PEM file? 01092 if(k <= 0) 01093 return ERROR_INVALID_SYNTAX; 01094 01095 //Length of the PEM structure 01096 length = k; 01097 01098 //Allocate a memory buffer to hold the decoded data 01099 buffer = cryptoAllocMem(length); 01100 //Failed to allocate memory? 01101 if(buffer == NULL) 01102 return ERROR_OUT_OF_MEMORY; 01103 01104 //Copy the contents of the PEM structure 01105 memcpy(buffer, input, length); 01106 01107 //Remove carriage returns and line feeds 01108 for(i = 0, j = 0; i < length; i++) 01109 { 01110 if(buffer[i] != '\r' && buffer[i] != '\n') 01111 buffer[j++] = buffer[i]; 01112 } 01113 01114 //Start of exception handling block 01115 do 01116 { 01117 //The PEM file is Base64 encoded... 01118 error = base64Decode(buffer, j, buffer, &length); 01119 //Failed to decode the file? 01120 if(error) 01121 break; 01122 01123 //Point to the resulting ASN.1 structure 01124 data = (uint8_t *) buffer; 01125 01126 //Display ASN.1 structure 01127 error = asn1DumpObject(data, length, 0); 01128 //Any error to report? 01129 if(error) 01130 break; 01131 01132 //The private key is encapsulated within a sequence 01133 error = asn1ReadTag(data, length, &tag); 01134 //Failed to decode ASN.1 tag? 01135 if(error) 01136 break; 01137 01138 //Enforce encoding, class and type 01139 error = asn1CheckTag(&tag, TRUE, ASN1_CLASS_UNIVERSAL, ASN1_TYPE_SEQUENCE); 01140 //The tag does not match the criteria? 01141 if(error) 01142 break; 01143 01144 //Point to the first field of the sequence 01145 data = tag.value; 01146 length = tag.length; 01147 01148 //Read the Version field 01149 error = asn1ReadTag(data, length, &tag); 01150 //Failed to decode ASN.1 tag? 01151 if(error) 01152 break; 01153 01154 //Enforce encoding, class and type 01155 error = asn1CheckTag(&tag, FALSE, ASN1_CLASS_UNIVERSAL, ASN1_TYPE_INTEGER); 01156 //The tag does not match the criteria? 01157 if(error) 01158 break; 01159 01160 //Skip the Version field 01161 data += tag.totalLength; 01162 length -= tag.totalLength; 01163 01164 //Read the PrivateKey field 01165 error = asn1ReadTag(data, length, &tag); 01166 //Failed to decode ASN.1 tag? 01167 if(error) 01168 break; 01169 01170 //Enforce encoding, class and type 01171 error = asn1CheckTag(&tag, FALSE, ASN1_CLASS_UNIVERSAL, ASN1_TYPE_OCTET_STRING); 01172 //The tag does not match the criteria? 01173 if(error) 01174 break; 01175 01176 //Read the EC private key 01177 error = mpiReadRaw(key, tag.value, tag.length); 01178 //Any error to report? 01179 if(error) 01180 break; 01181 01182 //Debug message 01183 TRACE_DEBUG("EC private key:\r\n"); 01184 TRACE_DEBUG_MPI(" ", key); 01185 01186 //End of exception handling block 01187 } while(0); 01188 } 01189 else 01190 { 01191 //Search for the beginning tag 01192 k = pemSearchTag(input, length, "-----BEGIN PRIVATE KEY-----", 27); 01193 //Failed to find the specified tag? 01194 if(k < 0) 01195 return ERROR_INVALID_SYNTAX; 01196 01197 //Advance the pointer over the tag 01198 input += k + 27; 01199 length -= k + 27; 01200 01201 //Search for the end tag 01202 k = pemSearchTag(input, length, "-----END PRIVATE KEY-----", 25); 01203 //Invalid PEM file? 01204 if(k <= 0) 01205 return ERROR_INVALID_SYNTAX; 01206 01207 //Length of the PEM structure 01208 length = k; 01209 01210 //Allocate a memory buffer to hold the decoded data 01211 buffer = cryptoAllocMem(length); 01212 //Failed to allocate memory? 01213 if(buffer == NULL) 01214 return ERROR_OUT_OF_MEMORY; 01215 01216 //Copy the contents of the PEM structure 01217 memcpy(buffer, input, length); 01218 01219 //Remove carriage returns and line feeds 01220 for(i = 0, j = 0; i < length; i++) 01221 { 01222 if(buffer[i] != '\r' && buffer[i] != '\n') 01223 buffer[j++] = buffer[i]; 01224 } 01225 01226 //Start of exception handling block 01227 do 01228 { 01229 //The PEM file is Base64 encoded... 01230 error = base64Decode(buffer, j, buffer, &length); 01231 //Failed to decode the file? 01232 if(error) 01233 break; 01234 01235 //Point to the resulting ASN.1 structure 01236 data = (uint8_t *) buffer; 01237 01238 //Display ASN.1 structure 01239 error = asn1DumpObject(data, length, 0); 01240 //Any error to report? 01241 if(error) 01242 break; 01243 01244 //The private key is encapsulated within a sequence 01245 error = asn1ReadTag(data, length, &tag); 01246 //Failed to decode ASN.1 tag? 01247 if(error) 01248 break; 01249 01250 //Enforce encoding, class and type 01251 error = asn1CheckTag(&tag, TRUE, ASN1_CLASS_UNIVERSAL, ASN1_TYPE_SEQUENCE); 01252 //The tag does not match the criteria? 01253 if(error) 01254 break; 01255 01256 //Point to the first field of the sequence 01257 data = tag.value; 01258 length = tag.length; 01259 01260 //Read the Version field 01261 error = asn1ReadTag(data, length, &tag); 01262 //Failed to decode ASN.1 tag? 01263 if(error) 01264 break; 01265 01266 //Enforce encoding, class and type 01267 error = asn1CheckTag(&tag, FALSE, ASN1_CLASS_UNIVERSAL, ASN1_TYPE_INTEGER); 01268 //The tag does not match the criteria? 01269 if(error) 01270 break; 01271 01272 //Skip the Version field 01273 data += tag.totalLength; 01274 length -= tag.totalLength; 01275 01276 //Read the PrivateKeyAlgorithmIdentifier field 01277 error = asn1ReadTag(data, length, &tag); 01278 //Failed to decode ASN.1 tag? 01279 if(error) 01280 break; 01281 01282 //Enforce encoding, class and type 01283 error = asn1CheckTag(&tag, TRUE, ASN1_CLASS_UNIVERSAL, ASN1_TYPE_SEQUENCE); 01284 //The tag does not match the criteria? 01285 if(error) 01286 break; 01287 01288 //Skip the PrivateKeyAlgorithmIdentifier field 01289 data += tag.totalLength; 01290 length -= tag.totalLength; 01291 01292 //The PrivateKey field is encapsulated within an octet string 01293 error = asn1ReadTag(data, length, &tag); 01294 //Failed to decode ASN.1 tag? 01295 if(error) 01296 break; 01297 01298 //Enforce encoding, class and type 01299 error = asn1CheckTag(&tag, FALSE, ASN1_CLASS_UNIVERSAL, ASN1_TYPE_OCTET_STRING); 01300 //The tag does not match the criteria? 01301 if(error) 01302 break; 01303 01304 //Display ASN.1 structure 01305 error = asn1DumpObject(tag.value, tag.length, 0); 01306 //Any error to report? 01307 if(error) 01308 break; 01309 01310 //Read the contents of the PrivateKey structure 01311 error = asn1ReadTag(tag.value, tag.length, &tag); 01312 //Failed to decode ASN.1 tag? 01313 if(error) 01314 break; 01315 01316 //Enforce encoding, class and type 01317 error = asn1CheckTag(&tag, TRUE, ASN1_CLASS_UNIVERSAL, ASN1_TYPE_SEQUENCE); 01318 //The tag does not match the criteria? 01319 if(error) 01320 break; 01321 01322 //Point to the first field of the sequence 01323 data = tag.value; 01324 length = tag.length; 01325 01326 //Read the Version field 01327 error = asn1ReadTag(data, length, &tag); 01328 //Failed to decode ASN.1 tag? 01329 if(error) 01330 break; 01331 01332 //Enforce encoding, class and type 01333 error = asn1CheckTag(&tag, FALSE, ASN1_CLASS_UNIVERSAL, ASN1_TYPE_INTEGER); 01334 //The tag does not match the criteria? 01335 if(error) 01336 break; 01337 01338 //Skip the Version field 01339 data += tag.totalLength; 01340 length -= tag.totalLength; 01341 01342 //Read the PrivateKey field 01343 error = asn1ReadTag(data, length, &tag); 01344 //Failed to decode ASN.1 tag? 01345 if(error) 01346 break; 01347 01348 //Enforce encoding, class and type 01349 error = asn1CheckTag(&tag, FALSE, ASN1_CLASS_UNIVERSAL, ASN1_TYPE_OCTET_STRING); 01350 //The tag does not match the criteria? 01351 if(error) 01352 break; 01353 01354 //Read the EC private key 01355 error = mpiReadRaw(key, tag.value, tag.length); 01356 //Any error to report? 01357 if(error) 01358 break; 01359 01360 //Debug message 01361 TRACE_DEBUG("EC private key:\r\n"); 01362 TRACE_DEBUG_MPI(" ", key); 01363 01364 //End of exception handling block 01365 } while(0); 01366 } 01367 01368 //Release previously allocated memory 01369 cryptoFreeMem(buffer); 01370 01371 //Clean up side effects if necessary 01372 if(error) 01373 mpiFree(key); 01374 01375 //Return status code 01376 return error; 01377 #else 01378 //Not implemented 01379 return ERROR_NOT_IMPLEMENTED; 01380 #endif 01381 } 01382 01383 01384 /** 01385 * @brief Decode a PEM file containing a certificate 01386 * @param[in,out] input Pointer to the PEM structure 01387 * @param[in,out] inputLength Length of the PEM structure 01388 * @param[in,out] output Pointer to the DER encoded certificate 01389 * @param[in,out] outputSize Size of the memory block that holds the DER certificate 01390 * @param[out] outputLength Length of the DER encoded certificate 01391 * @return Error code 01392 **/ 01393 01394 error_t pemReadCertificate(const char_t **input, size_t *inputLength, 01395 uint8_t **output, size_t *outputSize, size_t *outputLength) 01396 { 01397 error_t error; 01398 size_t length; 01399 size_t i; 01400 size_t j; 01401 int_t k; 01402 01403 //Check parameters 01404 if(input == NULL || inputLength == NULL) 01405 return ERROR_INVALID_PARAMETER; 01406 if(output == NULL || outputSize == NULL || outputLength == NULL) 01407 return ERROR_INVALID_PARAMETER; 01408 01409 //Search for the beginning tag 01410 k = pemSearchTag(*input, *inputLength, "-----BEGIN CERTIFICATE-----", 27); 01411 //Failed to find the specified tag? 01412 if(k < 0) 01413 return ERROR_END_OF_FILE; 01414 01415 //Advance the input pointer over the tag 01416 *input += k + 27; 01417 *inputLength -= k + 27; 01418 01419 //Search for the end tag 01420 k = pemSearchTag(*input, *inputLength, "-----END CERTIFICATE-----", 25); 01421 //Invalid PEM file? 01422 if(k <= 0) 01423 return ERROR_INVALID_SYNTAX; 01424 01425 //Length of the PEM structure 01426 length = k; 01427 01428 //Increase buffer size? 01429 if(length > *outputSize) 01430 { 01431 //Release previously allocated buffer if necessary 01432 if(*output != NULL) 01433 { 01434 cryptoFreeMem(*output); 01435 *output = NULL; 01436 *outputSize = 0; 01437 } 01438 01439 //Allocate a memory buffer to hold the decoded data 01440 *output = cryptoAllocMem(length); 01441 //Failed to allocate memory? 01442 if(*output == NULL) 01443 return ERROR_OUT_OF_MEMORY; 01444 01445 //Record the size of the buffer 01446 *outputSize = length; 01447 } 01448 01449 //Copy the contents of the PEM structure 01450 memcpy(*output, *input, length); 01451 01452 //Advance the input pointer over the certificate 01453 *input += length + 25; 01454 *inputLength -= length + 25; 01455 01456 //Remove carriage returns and line feeds 01457 for(i = 0, j = 0; i < length; i++) 01458 { 01459 if((*output)[i] != '\r' && (*output)[i] != '\n') 01460 (*output)[j++] = (*output)[i]; 01461 } 01462 01463 //Start of exception handling block 01464 do 01465 { 01466 //The PEM file is Base64 encoded... 01467 error = base64Decode((char_t *) *output, j, *output, &length); 01468 //Failed to decode the file? 01469 if(error) 01470 break; 01471 01472 //Display ASN.1 structure 01473 error = asn1DumpObject(*output, length, 0); 01474 //Any error to report? 01475 if(error) 01476 break; 01477 01478 //End of exception handling block 01479 } while(0); 01480 01481 //Clean up side effects 01482 if(error) 01483 { 01484 //Release previously allocated memory 01485 cryptoFreeMem(*output); 01486 *output = NULL; 01487 *outputSize = 0; 01488 } 01489 01490 //Size of the decoded certificate 01491 *outputLength = length; 01492 //Return status code 01493 return error; 01494 } 01495 01496 01497 /** 01498 * @brief Search a string for a given tag 01499 * @param[in] s String to search 01500 * @param[in] sLen Length of the string to search 01501 * @param[in] tag String containing the tag to search for 01502 * @param[in] tagLen Length of the tag 01503 * @return The index of the first occurrence of the tag in the string, 01504 * or -1 if the tag does not appear in the string 01505 **/ 01506 01507 int_t pemSearchTag(const char_t *s, size_t sLen, const char_t *tag, size_t tagLen) 01508 { 01509 size_t i; 01510 size_t j; 01511 01512 //Loop through input string 01513 for(i = 0; (i + tagLen) <= sLen; i++) 01514 { 01515 //Compare current substring with the given tag 01516 for(j = 0; j < tagLen; j++) 01517 { 01518 if(s[i + j] != tag[j]) 01519 break; 01520 } 01521 01522 //Check whether the tag has been found 01523 if(j == tagLen) 01524 return i; 01525 } 01526 01527 //The tag does not appear in the string 01528 return -1; 01529 } 01530 01531 #endif 01532
Generated on Tue Jul 12 2022 17:10:15 by
