BOOL CCookie::ParseExpires(LPCSTR lpszExpires, __time64_t& tmExpires) { int iLength = (int)strlen(lpszExpires); if(iLength == 0 || iLength > 50) return FALSE; char szMonth[10]; char szZone[10]; tm t = {0}; if(sscanf( lpszExpires, "%*[^, ]%*[, ]%2d%*[-/ ]%8[^-/ ]%*[-/ ]%4d %2d:%2d:%2d %8c", &t.tm_mday, szMonth, &t.tm_year, &t.tm_hour, &t.tm_min, &t.tm_sec, szZone) != 7) return FALSE; if(t.tm_year < 70) t.tm_year += 100; else if (t.tm_year > 100) t.tm_year -= 1900; int i = 0; int size = _countof(s_short_month); for(; i < size; i++) { if(strnicmp(szMonth, s_short_month[i], 3) == 0) break; } if(i == size) return FALSE; t.tm_mon = i; CStringA strZone = szZone; int iZone = 0; int iMix = 0; int iPos = strZone.Find('+'); if(iPos >= 0) iMix = 1; else { iPos = strZone.Find('-'); if(iPos >= 0) iMix = -1; } if(iPos >= 0) { strZone = strZone.Mid(iPos + 1); strZone.Remove(':'); int val = atoi(strZone); if(val > 0) { int minutes = val % 100; int hours = val / 100; iZone = iMix * (minutes * 60 + hours * 3600); } } tmExpires = GetUTCTime(t, iZone); return tmExpires >= 0; }
// Write signed variable EFI_STATUS SetSignedVariable(IN CHAR16 *DatabaseName, IN EFI_GUID *DatabaseGuid, IN UINT32 Attributes, IN VOID *Database, IN UINTN DatabaseSize) { EFI_STATUS Status; EFI_VARIABLE_AUTHENTICATION_2 *Authentication; UINTN Size, NameLen; UINTN DataSize = 0; EFI_TIME Timestamp; VOID *Data = NULL; BIO *BioData = NULL; PKCS7 *p7; X509 *Certificate = NULL; EVP_PKEY *PrivateKey = NULL; const EVP_MD *md; // Check parameters if ((DatabaseName == NULL) || (DatabaseGuid == NULL)) { return EFI_INVALID_PARAMETER; } DBG("Setting secure variable: %g %s 0x%X (0x%X)\n", DatabaseGuid, DatabaseName, Database, DatabaseSize); NameLen = StrLen(DatabaseName); if (NameLen == 0) { return EFI_INVALID_PARAMETER; } // Get the current time DBG("Getting timestamp ...\n"); Status = GetUTCTime(&Timestamp); if (EFI_ERROR(Status)) { return Status; } DBG("Timestamp: %t\n", Timestamp); // In user mode we need to sign the database with exchange key if (!gSettings.SecureBootSetupMode) { // Initialize the cyphers and digests ERR_load_crypto_strings(); OpenSSL_add_all_digests(); OpenSSL_add_all_ciphers(); // Create signing certificate BioData = BIO_new_mem_buf((void *)gSecureBootExchangeKey, sizeof(gSecureBootExchangeKey)); if (BioData == NULL) { return EFI_OUT_OF_RESOURCES; } Certificate = PEM_read_bio_X509(BioData, NULL, NULL, NULL); BIO_free(BioData); if (Certificate == NULL) { return EFI_OUT_OF_RESOURCES; } // Create signing private key BioData = BIO_new_mem_buf((void *)gSecureBootExchangePrivateKey, sizeof(gSecureBootExchangePrivateKey)); if (BioData == NULL) { return EFI_OUT_OF_RESOURCES; } PrivateKey = PEM_read_bio_PrivateKey(BioData, NULL, NULL, NULL); BIO_free(BioData); if (PrivateKey == NULL) { X509_free(Certificate); return EFI_OUT_OF_RESOURCES; } // Do the actual signing process BioData = BIO_new(BIO_s_mem()); BIO_write(BioData, DatabaseName, (int)StrLen(DatabaseName)); BIO_write(BioData, DatabaseGuid, sizeof(EFI_GUID)); BIO_write(BioData, &Attributes, sizeof(UINT32)); BIO_write(BioData, &Timestamp, sizeof(EFI_TIME)); BIO_write(BioData, Database, (int)DatabaseSize); md = EVP_get_digestbyname("SHA256"); p7 = PKCS7_new(); PKCS7_set_type(p7, NID_pkcs7_signed); PKCS7_content_new(p7, NID_pkcs7_data); PKCS7_sign_add_signer(p7, Certificate, PrivateKey, md, PKCS7_BINARY | PKCS7_DETACHED | PKCS7_NOSMIMECAP); PKCS7_set_detached(p7, 1); PKCS7_final(p7, BioData, PKCS7_BINARY | PKCS7_DETACHED | PKCS7_NOSMIMECAP); X509_free(Certificate); EVP_PKEY_free(PrivateKey); DataSize = i2d_PKCS7(p7, NULL); Data = AllocateZeroPool(DataSize); i2d_PKCS7(p7, (unsigned char **)&Data); PKCS7_free(p7); // Set the authentication buffer size Size = sizeof(EFI_TIME) + sizeof(EFI_GUID) + sizeof(UINT32) + sizeof(UINT16) + sizeof(UINT16) + DataSize; } else { // In setup mode we don't need to sign, so just set the database DBG("In setup mode, not signing ...\n"); Size = sizeof(EFI_TIME) + sizeof(EFI_GUID) + sizeof(UINT32) + sizeof(UINT16) + sizeof(UINT16) + DatabaseSize; } // Create the authentication buffer DBG("Creating authentication ...\n"); Authentication = (EFI_VARIABLE_AUTHENTICATION_2 *)AllocateZeroPool(Size); if (Authentication == NULL) { if (Data != NULL) { FreePool(Data); } return EFI_OUT_OF_RESOURCES; } // Set the certificate elements CopyMem(&(Authentication->TimeStamp), &Timestamp, sizeof(EFI_TIME)); Authentication->AuthInfo.Hdr.dwLength = (UINT32)(sizeof(EFI_GUID) + sizeof(UINT32) + sizeof(UINT16) + sizeof(UINT16) + DataSize); Authentication->AuthInfo.Hdr.wRevision = 0x0200; Authentication->AuthInfo.Hdr.wCertificateType = WIN_CERT_TYPE_EFI_GUID; CopyMem(&(Authentication->AuthInfo.CertType), &gEfiCertPkcs7Guid, sizeof(EFI_GUID)); // Copy the data into the authentication if (Data != NULL) { CopyMem(((UINT8 *)Authentication) + sizeof(EFI_TIME) + sizeof(EFI_GUID) + sizeof(UINT32) + sizeof(UINT16) + sizeof(UINT16), Data, DataSize); FreePool(Data); } else { CopyMem(((UINT8 *)Authentication) + sizeof(EFI_TIME) + sizeof(EFI_GUID) + sizeof(UINT32) + sizeof(UINT16) + sizeof(UINT16), Database, DatabaseSize); //Payload, PayloadSize); } DBG("Writing secure variable 0x%X (0x%X) ...\n", Authentication, Size); // Write the database variable Status = gRT->SetVariable(DatabaseName, DatabaseGuid, SET_DATABASE_ATTRIBUTES, Size, Authentication); // Cleanup the authentication buffer FreePool(Authentication); return Status; }