OpenSSL: how to get x509 -subject_hash "manually"? - hash

I'm trying to get the same result as
openssl X509 -in certificate.pem -subject_hash
without using the function directly but instead by extracting the cerrtificate name and building the propper canonical representation to then take the sha-1 hash from. Is this possible? Something like
openssl x509 -in certificate.pem -subject -noout -nameopt dn_rev -nameopt RFC2253 | tr '[:upper:]' '[:lower:]' | openssl dgst -sha1 -binary | xxd -p
and then truncating the hash to 4bytes or so... so far I didn't get it though
$ openssl x509 -in .pem -subject_hash -noout
cc952886
$openssl x509 -in certificate.pem -subject -noout -nameopt RFC2253 | tr '[:upper:]' '[:lower:]' | openssl dgst -sha1 -binary | xxd -p
0b6a015b2a7ed2a5f3695f1d46a0c20006de300a
The respective c code is here: https://github.com/openssl/openssl/blob/d53b437f9992f974c1623e9b9b9bdf053aefbcc3/crypto/x509/x509_cmp.c#L261
unsigned long X509_NAME_hash_ex(const X509_NAME *x, OSSL_LIB_CTX *libctx,
const char *propq, int *ok)
{
unsigned long ret = 0;
unsigned char md[SHA_DIGEST_LENGTH];
EVP_MD *sha1 = EVP_MD_fetch(libctx, "SHA1", propq);
/* Make sure X509_NAME structure contains valid cached encoding */
i2d_X509_NAME(x, NULL);
if (ok != NULL)
*ok = 0;
if (sha1 != NULL
&& EVP_Digest(x->canon_enc, x->canon_enclen, md, NULL, sha1, NULL)) {
ret = (((unsigned long)md[0]) | ((unsigned long)md[1] << 8L) |
((unsigned long)md[2] << 16L) | ((unsigned long)md[3] << 24L)
) & 0xffffffffL;
if (ok != NULL)
*ok = 1;
}
EVP_MD_free(sha1);
return ret;
}
and the canonical representation of the name is set here: https://github.com/openssl/openssl/blob/256d41d4371720ccfe1a4fead6bd28ed5071bcdd/crypto/x509/x_name.c#L303
/*
* This function generates the canonical encoding of the Name structure. In
* it all strings are converted to UTF8, leading, trailing and multiple
* spaces collapsed, converted to lower case and the leading SEQUENCE header
* removed. In future we could also normalize the UTF8 too. By doing this
* comparison of Name structures can be rapidly performed by just using
* memcmp() of the canonical encoding. By omitting the leading SEQUENCE name
* constraints of type dirName can also be checked with a simple memcmp().
*/
static int x509_name_canon(X509_NAME *a)
{
unsigned char *p;
STACK_OF(STACK_OF_X509_NAME_ENTRY) *intname;
STACK_OF(X509_NAME_ENTRY) *entries = NULL;
X509_NAME_ENTRY *entry, *tmpentry = NULL;
int i, set = -1, ret = 0, len;
OPENSSL_free(a->canon_enc);
a->canon_enc = NULL;
/* Special case: empty X509_NAME => null encoding */
if (sk_X509_NAME_ENTRY_num(a->entries) == 0) {
a->canon_enclen = 0;
return 1;
}
intname = sk_STACK_OF_X509_NAME_ENTRY_new_null();
if (intname == NULL) {
ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE);
goto err;
}
for (i = 0; i < sk_X509_NAME_ENTRY_num(a->entries); i++) {
entry = sk_X509_NAME_ENTRY_value(a->entries, i);
if (entry->set != set) {
entries = sk_X509_NAME_ENTRY_new_null();
if (entries == NULL)
goto err;
if (!sk_STACK_OF_X509_NAME_ENTRY_push(intname, entries)) {
sk_X509_NAME_ENTRY_free(entries);
ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE);
goto err;
}
set = entry->set;
}
tmpentry = X509_NAME_ENTRY_new();
if (tmpentry == NULL) {
ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE);
goto err;
}
tmpentry->object = OBJ_dup(entry->object);
if (tmpentry->object == NULL) {
ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE);
goto err;
}
if (!asn1_string_canon(tmpentry->value, entry->value))
goto err;
if (!sk_X509_NAME_ENTRY_push(entries, tmpentry)) {
ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE);
goto err;
}
tmpentry = NULL;
}
/* Finally generate encoding */
len = i2d_name_canon(intname, NULL);
if (len < 0)
goto err;
a->canon_enclen = len;
p = OPENSSL_malloc(a->canon_enclen);
if (p == NULL) {
ERR_raise(ERR_LIB_X509, ERR_R_MALLOC_FAILURE);
goto err;
}
a->canon_enc = p;
i2d_name_canon(intname, &p);
ret = 1;
err:
X509_NAME_ENTRY_free(tmpentry);
sk_STACK_OF_X509_NAME_ENTRY_pop_free(intname,
local_sk_X509_NAME_ENTRY_pop_free);
return ret;
}

Possibly, but you need to know all the Object Ids (OIDs) of all the relative Distinguished Name components (RDNs). e.g. CN=2.5.4.2 and then the ASN1 encoding. You need to rebuild the binary ASN1 blob then take the sha1 digest then take the first 4 bytes of that in reverse order.
I've created a bash script which uses the nameopts to get the subject in as close to ASN1 encoding as possible and also the OIDs. Then I've mashed all that together. https://github.com/nimpo/hash-bash-ssl

Related

Segmentation Fault in EVP_DigestFinal_ex -> SHA256_Final due to NULL algctx

using Linux (ubuntu 20.04) machine, openssl 3.0.7 is installed , running a sample code for signing.
we followed below procedure for signing. getting segmentation fault in EVP_DigestFinal_ex.
segmentation fault is happening due to mdctx->algctx=0x0. while debugging the code mdctx->algctx is updated in EVP_DigestInit_ex but latter it was freed in EVP_DigestSignInit. not sure what we are missing and how to update mdctx->algctx to avoid the crash.
#include <stdio.h>
#include <string.h>
#include <openssl/evp.h>
#include <openssl/provider.h>
EVP_PKEY *pkey = NULL;
generate_key(){
EVP_PKEY_CTX *ctx=NULL;
pkey=EVP_PKEY_new();
ctx=EVP_PKEY_CTX_new(pkey,NULL);
ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL);
if (!ctx)
printf(" key gen failed");
if (EVP_PKEY_keygen_init(ctx) <= 0)
printf(" key gen failed");
if (EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, 512) <= 0)
printf(" key gen failed");
/* Generate key */
if (EVP_PKEY_keygen(ctx, &pkey) <= 0)
printf(" key gen failed");
}
int main(int argc, char *argv[])
{
EVP_MD_CTX *mdctx;
const EVP_MD *m_md;
const EVP_MD *md;
EVP_PKEY *m_key;
EVP_PKEY *ed_pkey = NULL;
EVP_PKEY_CTX *ed_pctx = NULL;
// OSSL_PROVIDER *default;
size_t sign_len = 0;
u_int8_t m_sign_buf[2048];
int ret = 0;
char mess1[] = "Test Message\n";
char mess2[] = "Hello World\n";
unsigned char *outdigest = NULL;
unsigned int md_len = 0, i;
printf("args : %s\n",argv[1]);
//default = OSSL_PROVIDE_load(NULL, "default");
//md = EVP_get_digestbyname("SHA256");
//md = EVP_sha256();
md = EVP_MD_fetch(NULL, "SHA256", NULL); //;
if (md == NULL) {
printf("Unknown message digest %s\n", argv[1]);
exit(1);
}
generate_key();
printf("value of md %s\n",md);
mdctx = EVP_MD_CTX_new();
if((EVP_DigestInit_ex(mdctx, md, NULL)) != 1)
printf("EVP_DigestInit_ex failed \n");
if((EVP_DigestSignInit(mdctx, NULL, md, NULL, pkey)) != 1)
printf("EVP_DigestSignInit failed \n");
if((EVP_DigestSignUpdate(mdctx, mess1, strlen(mess1))) != 1)
printf("EVP_DigestSignUpdate failed \n");
//EVP_DigestUpdate(mdctx, mess2, strlen(mess2));
if((EVP_DigestSignFinal(mdctx, (u_int8_t*)NULL, &sign_len)) != 1)
printf("EVP_DigestSignFinal failed \n");
if((EVP_DigestSignFinal(mdctx, m_sign_buf, &sign_len)) != 1)
printf("EVP_DigestSignFinal 2 failed \n");
/* Allocate the output buffer */
outdigest = OPENSSL_malloc(EVP_MD_get_size(md));
if (outdigest == NULL)
printf("outdigest failed \n");
if((EVP_DigestFinal_ex(mdctx, outdigest, &md_len)) != 1)
printf("EVP_DigestFinal_ex failed \n");
EVP_MD_CTX_free(mdctx);
/* Print out the digest result */
BIO_dump_fp(stdout, outdigest, &md_len);
exit(0);
}
`
```
Thanks,
while debugging the code mdctx->algctx is updated in EVP_DigestInit_ex but latter it was freed in EVP_DigestSignInit. not sure what we are missing and how to update mdctx->algctx to avoid the crash.
CRASH Info:
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7d99422 in SHA256_Final (md=0x5555555a88d0 "\250UUU\005", c=0x0)
    at ../openssl-3.0.7/include/crypto/md32_common.h:194
194         size_t n = c->num;
(gdb) bt
#0  0x00007ffff7d99422 in SHA256_Final (md=0x5555555a88d0 "\250UUU\005", c=0x0)
    at ../openssl-3.0.7/include/crypto/md32_common.h:194
#1  0x00007ffff7e2628c in sha256_internal_final (ctx=0x0, out=0x5555555a88d0 "\250UUU\005", outl=0x7fffffffda98,
    outsz=32) at ../openssl-3.0.7/providers/implementations/digests/sha2_prov.c:72
#2  0x00007ffff7cbadf6 in EVP_DigestFinal_ex (ctx=0x555555580d80, md=0x5555555a88d0 "\250UUU\005",
    isize=0x7fffffffdad8) at ../openssl-3.0.7/crypto/evp/digest.c:446
#3  0x000055555555575f in main (argc=1, argv=0x7fffffffe458) at test2.c:90

Most UEFI protocols are reported as "unsupported"

I'm writing an EFI executable on a SoC device (Up Board) to help us automate BIOS updates and PXE boots for installating our software on numerous devices.
The problem I have is that seemingly most of the protocols in the specification are "unsupported" on this platform, even basic file system tasks. The only one I've successfully used is the LOADED_IMAGE_PROTOCOL. I'm using gnu-efi to compile the code, basing my code to this example https://mjg59.dreamwidth.org/18773.html. Is there something I'm doing wrong, or is this simply the firmware absolutely not implementing any of the protocols?
The American Megatrends utility "AfuEfix64.efi" is capable of retrieving BIOS information, and the SoC BIOS updates are done using an Intel's EFI executable. Both are closed source, unfortunately. My initial idea would have been to write a script that parses the output from these executables, but I don't think the EFI shell has much features for this type of tasks, so I moved on to writing an EFI executable to perform this.
Minimal code showing this:
#include <efi.h>
#include <efilib.h>
#include <x86_64/efibind.h>
// gnu-efi does not currently define firmware management
// https://raw.githubusercontent.com/tianocore/edk2/master/MdePkg/Include/Protocol/FirmwareManagement.h
#include "efifirmware.h"
// gnu-efi does not currently define this
#define EFI_LOAD_FILE2_PROTOCOL_GUID \
{ 0x4006c0c1, 0xfcb3, 0x403e, \
{ 0x99, 0x6d, 0x4a, 0x6c, 0x87, 0x24, 0xe0, 0x6d }}
typedef EFI_LOAD_FILE_PROTOCOL EFI_LOAD_FILE2_PROTOCOL;
void tryProtocol(EFI_GUID proto_guid, void** out, const CHAR16* name,
EFI_HANDLE imageHandle, EFI_SYSTEM_TABLE* systemTable) {
EFI_STATUS status;
status = uefi_call_wrapper(systemTable->BootServices->HandleProtocol, 3,
imageHandle, &proto_guid, out);
if (EFI_ERROR(status)) {
Print(L"HandleProtocol error for %s: %r\n", name, status);
} else {
Print(L"Protocol %s is supported\n", name);
}
}
void tryProtocols(EFI_HANDLE imgh, EFI_SYSTEM_TABLE* syst) {
EFI_LOADED_IMAGE* loaded_image = NULL;
EFI_GUID guid_imgprot = LOADED_IMAGE_PROTOCOL;
tryProtocol(guid_imgprot, (void**)&loaded_image,
L"LOADED_IMAGE_PROTOCOL", imgh, syst);
Print(L"Image base: %lx\n", loaded_image->ImageBase);
Print(L"Image size: %lx\n", loaded_image->ImageSize);
Print(L"Image file: %s\n", DevicePathToStr(loaded_image->FilePath));
EFI_FIRMWARE_MANAGEMENT_PROTOCOL* fw_manage = NULL;
EFI_GUID guid_fwman_prot = EFI_FIRMWARE_MANAGEMENT_PROTOCOL_GUID;
tryProtocol(guid_fwman_prot, (void**)&fw_manage,
L"FIRMWARE_MANAGEMENT_PROTOCOL", imgh, syst);
EFI_LOAD_FILE_PROTOCOL* load_file = NULL;
EFI_GUID guid_loadf_prot = EFI_LOAD_FILE_PROTOCOL_GUID;
tryProtocol(guid_loadf_prot, (void**)&load_file,
L"LOAD_FILE_PROTOCOL", imgh, syst);
EFI_LOAD_FILE2_PROTOCOL* load_file2 = NULL;
EFI_GUID guid_loadf2_prot = EFI_LOAD_FILE2_PROTOCOL_GUID;
tryProtocol(guid_loadf2_prot, (void**)&load_file2,
L"LOAD_FILE2_PROTOCOL", imgh, syst);
EFI_SIMPLE_FILE_SYSTEM_PROTOCOL* simple_fs = NULL;
EFI_GUID guid_simple_fs_prot = EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID;
tryProtocol(guid_simple_fs_prot, (void**)&simple_fs,
L"SIMPLE_FILE_SYSTEM_PROTOCOL", imgh, syst);
EFI_DISK_IO_PROTOCOL* disk = NULL;
EFI_GUID guid_disk_io_prot = EFI_DISK_IO_PROTOCOL_GUID;
tryProtocol(guid_disk_io_prot, (void**)&disk,
L"DISK_IO_PROTOCOL", imgh, syst);
EFI_BLOCK_IO_PROTOCOL* block = NULL;
EFI_GUID guid_block_io_prot = EFI_BLOCK_IO_PROTOCOL_GUID;
tryProtocol(guid_block_io_prot, (void**)&block,
L"BLOCK_IO_PROTOCOL", imgh, syst);
}
EFI_STATUS
EFIAPI
efi_main (EFI_HANDLE imageHandle, EFI_SYSTEM_TABLE* systemTable) {
InitializeLib(imageHandle, systemTable);
Print(L"Image loaded\n");
tryProtocols(imageHandle, systemTable);
return EFI_SUCCESS;
}
Here's the output for running it:
EFI Shell version 2.40 [5.11]
Current running mode 1.1.2
Device mapping table
fs0 :HardDisk - Alias hd6b blk0
PciRoot(0x0)/Pci(0x10,0x0)/Ctrl(0x0)/HD(1,GPT,2DCDDADD-8F3A-4A77-94A9-010A8C700BB8,0x800,0x100000)
fs1 :Removable HardDisk - Alias hd9g0a0b blk1
PciRoot(0x0)/Pci(0x14,0x0)/USB(0x6,0x0)/USB(0x0,0x0)/HD(1,MBR,0x528E6A1F,0x800,0x1CDE800)
blk0 :HardDisk - Alias hd6b fs0
PciRoot(0x0)/Pci(0x10,0x0)/Ctrl(0x0)/HD(1,GPT,2DCDDADD-8F3A-4A77-94A9-010A8C700BB8,0x800,0x100000)
blk1 :Removable HardDisk - Alias hd9g0a0b fs1
PciRoot(0x0)/Pci(0x14,0x0)/USB(0x6,0x0)/USB(0x0,0x0)/HD(1,MBR,0x528E6A1F,0x800,0x1CDE800)
blk2 :HardDisk - Alias (null)
PciRoot(0x0)/Pci(0x10,0x0)/Ctrl(0x0)/HD(2,GPT,8AC0F94E-3CA2-4C03-BE00-3A69721CC391,0x100800,0x1C1F7DF)
blk3 :BlockDevice - Alias (null)
PciRoot(0x0)/Pci(0x10,0x0)/Ctrl(0x0)
blk4 :BlockDevice - Alias (null)
PciRoot(0x0)/Pci(0x10,0x0)/Ctrl(0x1)
blk5 :BlockDevice - Alias (null)
PciRoot(0x0)/Pci(0x10,0x0)/Ctrl(0x2)
blk6 :Removable BlockDevice - Alias (null)
PciRoot(0x0)/Pci(0x14,0x0)/USB(0x6,0x0)/USB(0x0,0x0)
Press ESC in 4 seconds to skip startup.nsh, any other key to continue.
fs1:\> tryprotocols.efi
Image loaded
Protocol LOADED_IMAGE_PROTOCOL is supported
Image base: 55BA6000
Image size: F000
Image file: \/tryprotocols.efi
HandleProtocol error for FIRMWARE_MANAGEMENT_PROTOCOL: Unsupported
HandleProtocol error for LOAD_FILE_PROTOCOL: Unsupported
HandleProtocol error for LOAD_FILE2_PROTOCOL: Unsupported
HandleProtocol error for SIMPLE_FILE_SYSTEM_PROTOCOL: Unsupported
HandleProtocol error for DISK_IO_PROTOCOL: Unsupported
HandleProtocol error for BLOCK_IO_PROTOCOL: Unsupported
fs1:\>
And here's the Makefile I use to compile it:
ARCH=x86_64
OBJS=tryprotocols.o
TARGET=tryprotocols.efi
TARGET_SO=$(TARGET:.efi=.so)
GNUEFIDIR=/home/gekko/gnu-efi-3.0.8
EFIINC=$(GNUEFIDIR)/inc
EFIINCS=-I$(EFIINC) -I$(EFIINC)/$(ARCH) -I$(EFIINC)/protocol
LIB=$(GNUEFIDIR)/$(ARCH)/lib
EFILIB=$(GNUEFIDIR)/gnuefi
EFI_CRT_OBJS=$(GNUEFIDIR)/$(ARCH)/gnuefi/crt0-efi-$(ARCH).o
EFI_LDS=$(EFILIB)/elf_$(ARCH)_efi.lds
CFLAGS=$(EFIINCS) -fno-stack-protector -fpic \
-fshort-wchar -mno-red-zone -Wall
ifeq ($(ARCH),x86_64)
CFLAGS += -DEFI_FUNCTION_WRAPPER
endif
LDFLAGS=-nostdlib -znocombreloc -T $(EFI_LDS) -shared \
-Bsymbolic -L $(EFILIB) -L $(LIB) $(EFI_CRT_OBJS)
all: $(TARGET)
$(TARGET_SO): $(OBJS)
ld $(LDFLAGS) $(OBJS) -o $# -lefi -lgnuefi
%.efi: %.so
objcopy -j .text -j .sdata -j .data -j .dynamic \
-j .dynsym -j .rel -j .rela -j .reloc \
--target=efi-app-$(ARCH) $^ $#
clean:
rm -f *.o
rm -f $(TARGET)
rm -f $(TARGET_SO)
EDIT: Modified version that properly uses LocateProtocol() to find the protocols, and uses them to open and close a file.
#include <efi.h>
#include <efilib.h>
#include <x86_64/efibind.h>
BOOLEAN tryProtocol(EFI_GUID proto_guid, void** out, const CHAR16* name,
EFI_HANDLE imageHandle, EFI_SYSTEM_TABLE* systemTable) {
*out = NULL;
EFI_STATUS status;
EFI_HANDLE interface = NULL;
status = uefi_call_wrapper(systemTable->BootServices->LocateProtocol, 3,
&proto_guid, NULL, &interface);
if (EFI_ERROR(status)) {
Print(L"LocateProtocol error for %s: %r\n", name, status);
return FALSE;
}
Print(L"Locate protocol address: %s, %x\n", name, interface);
*out = interface;
return TRUE;
}
EFI_STATUS
EFIAPI
efi_main (EFI_HANDLE imageHandle, EFI_SYSTEM_TABLE* systemTable) {
InitializeLib(imageHandle, systemTable);
Print(L"Image loaded\n");
EFI_LOADED_IMAGE* loaded_image = NULL;
EFI_GUID guid_imgprot = LOADED_IMAGE_PROTOCOL;
if (tryProtocol(guid_imgprot, (void**)&loaded_image,
L"LOADED_IMAGE_PROTOCOL", imageHandle, systemTable) != TRUE) {
Print(L"Missing required protocol. Aborting\n");
return EFI_SUCCESS;
}
Print(L"Image base: %lx\n", loaded_image->ImageBase);
Print(L"Image size: %lx\n", loaded_image->ImageSize);
Print(L"Image file: %s\n", DevicePathToStr(loaded_image->FilePath));
EFI_SIMPLE_FILE_SYSTEM_PROTOCOL* simple_fs = NULL;
EFI_GUID guid_simple_fs_prot = EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID;
if (tryProtocol(guid_simple_fs_prot, (void**)&simple_fs,
L"EFI_SIMPLE_FILE_SYSTEM_PROTOCOL", imageHandle, systemTable) != TRUE) {
Print(L"Missing required protocol. Aborting\n");
return EFI_SUCCESS;
}
EFI_FILE_PROTOCOL* vol_proto = NULL;
EFI_STATUS status;
Print(L"dereffing\n");
Print(L"address of OpenVolume: %x\n", simple_fs->OpenVolume);
status = uefi_call_wrapper(simple_fs->OpenVolume, 2, simple_fs, &vol_proto);
if (EFI_ERROR(status)) {
Print(L"Error opening volume: %r\n", status);
return EFI_SUCCESS;
}
Print(L"SIMPLE_FILE_SYSTEM volume opened\n");
EFI_FILE_PROTOCOL* f;
CHAR16 fname[10] = L"foo.txt\0";
UINT64 openmode = EFI_FILE_MODE_READ;
UINT64 attr = 0;
status = uefi_call_wrapper(vol_proto->Open, 5, vol_proto, &f, fname, openmode, attr);
if (EFI_ERROR(status)) {
Print(L"Error opening file: %r\n", status);
return EFI_SUCCESS;
}
Print(L"opened file %s\n", fname);
// Spec says can only return EFI_SUCCESS
status = uefi_call_wrapper(vol_proto->Close, 1, f);
Print(L"Closed file\n");
return EFI_SUCCESS;
}
Where and how to access a specific protocol is not statically defined by the UEFI specification, but something that needs to be discovered at runtime. While a bit arduous, it makes it possible to write applications/drivers portable across vastly different UEFI implementations that all conform to the specification.
So you need to LocateProtocol() on each protocol you are intending to use before you can make use of HandleProtocol().
You get away with LOADED_IMAGE_PROTOCOL because that one is initialized with your ImageHandle referring to the instance of the currently executing image (your program).
This is covered in Matthew's post under the section That covers how to use protocols attached to the image handle. How about protocols that are attached to other handles?.

Encryption using public key

My code:
SecKeyRef oPublicKey = [self getPublicKeyRef];
SecKeyRef oPrivateKey = [self getPrivateKeyRef];
CFDictionaryRef myDictionary;
CFTypeRef keys[2];
CFTypeRef values[2];
// Initialize dictionary of key params
keys[0] = kSecAttrKeyType;
values[0] = kSecAttrKeyTypeRSA;
keys[1] = kSecAttrKeySizeInBits;
int iByteSize = 1024;
values[1] = CFNumberCreate( NULL, kCFNumberIntType, &iByteSize );
myDictionary = CFDictionaryCreate( NULL, keys, values, sizeof(keys) / sizeof(keys[0]), NULL, NULL );
// Generate keys
OSStatus status = SecKeyGeneratePair( myDictionary, &oPublicKey, &oPrivateKey );
if ( status != 0 )
NSLog( #"SecKeyGeneratePair failed" );
// Encrypt some data
uint8_t* pPlainText = (uint8_t*)"6921";
uint8_t aCipherText[1024];
size_t iCipherLength = 1024;
status = SecKeyEncrypt( oPublicKey, kSecPaddingPKCS1, pPlainText, strlen( (char*)pPlainText ) + 1, &aCipherText[0], &iCipherLength );
if ( status != 0 )
NSLog( #"SecKeyEncrypt failed" );
NSMutableData *data12=[[NSMutableData alloc] init];
[data12 appendBytes:aCipherText length:strlen( (char*)aCipherText ) + 1];
NSString *string1 = [[NSString alloc]initWithData:data12 encoding:NSASCIIStringEncoding];
NSLog(#"Encrypted Text:::%#",string1);
// Decrypt the data
uint8_t aPlainText[1024];
size_t iPlainLength = 1024;
status = SecKeyDecrypt( oPrivateKey, kSecPaddingPKCS1, &aCipherText[0], iCipherLength, &aPlainText[0], &iPlainLength );
if ( status != 0 )
NSLog( #"SecKeyDecrypt failed" );
NSLog(#"FINAL decrypted text: %s", aPlainText);
I am using this code for encryption but we are getting output like:
N$) : )¥=wÞ¢#4+ ’MO, œÝՑ#2< xՁ™‘Hþ a  f¦šU;f£Æì ø¤VØ´ÿ ÷ påcx ¨¢¯Ô)Õ#k Ë«: çÑ5
õ°7\ہ‰z~“9GX>M¼êe뿆w¥ro¬ ›gP4s2µ)9; p
But how to get NSString format ?Is there any wrong step in my code?
Always pad your plain text. PKCS #1 is the standard padding for RSA encryption.
Also, be aware that with RSA public key encryption, you can only encrypt/decrypt data up to the size of the key (minus a few overhead bytes).
Public key encryption is typically used only to encrypt a key (and hash), which is then used for symmetric encryption (and verification) of the actual payload.

How to use expat-parser with Russian charsets?

I tried to use expat for XML parsing, and I have Russian symbols in XML file, this symbols incorrectly interpret by expat.
I got expired_str: Русский текст
Instead of: Русский текст
Here is my cutted code:
static int xmlParseStartup(char *buffer, int n, START_UP_T *startUp_sp)
{
void *buff;
XML_Parser parser_p = XML_ParserCreate("UTF-8");
if (!parser_p)
{
DEBUG("Unable to create parser!\n");
return RES_ERR;
}
XML_SetUserData(parser_p, (void *)startUp_sp);
XML_SetElementHandler(parser_p, startElement, endElement);
buff = XML_GetBuffer(parser_p, n);
memcpy(buff, buffer, n);
if (XML_STATUS_ERROR == XML_ParseBuffer(parser_p, n, TRUE))
{
DEBUG("%s at line %" XML_FMT_INT_MOD "u\n",
XML_ErrorString(XML_GetErrorCode(parser_p)),
XML_GetCurrentLineNumber(parser_p));
return RES_ERR;
}
return RES_OK;
}
static void XMLCALL startElement(void *userData,
const char *name,
const char **atts)
{
int i;
START_UP_T *startUp_sp = (START_UP_T *)userData;
for (i = 0; i < startUp_sp->depthPtr; i++)
{
fprintf(stderr, ".");
}
DEBUG("[%d]name: %s\n", startUp_sp->depthPtr, name);
if (0 == strcmp(name, "response"))
{
if (0 == strcmp(atts[i], "result"))
{
startUp_sp->result = atoi(atts[3]);
DEBUG("RESULT: %d\n", startUp_sp->result);
}
else if (0 == strcmp(atts[i], "status_str"))
{
strcpy(startUp_sp->expired_str, atts[3]);
DEBUG("EXPIRED_STR: %s\n", startUp_sp->expired_str);
}
else if (0 == strcmp(atts[i], "status_width"))
{
startUp_sp->status_width = atoi(atts[3]);
}
}
startUp_sp->depthPtr += 1;
}
static void XMLCALL endElement(void *userData,
const char *name)
{
START_UP_T *startUp_sp = (START_UP_T *)userData;
startUp_sp->depthPtr -= 1;
}
XML file:
<?xml version="1.0" encoding="UTF-8"?>
<startup>
<response name="result" value="0"/>
<response name="status_str" value="Русский текст"/>
<response name="status_width" value="120"/>
</startup>
You get a cp1251 representation of the UTF-8 char*-typed string, so the expat actually works fine - it is the console output you're having problems with.
If it is not the case, check for the utf8 marker at the beginning of the xml file (239, 187, 191 bytes in ASCII codes, or "п>ї" without quotes in CP-1251).
One more: You should check the actual encoding of the .xml file, looks like it is not what you think it is (utf-8). What editor do you use to create the file ?
The CP1251 representation of UTF-8 "Русский текст" string is "Р С_С_С_РєРёР№ С'РчРєС_С'".

LSP packet modify

anybody care to share some insights on how to use LSP for packet modifying ?
I am using the non IFS subtype and I can see how (pseudo?) packets first enter WSPRecv. But how do I modify them ? My inquiry is about one single HTTP response that causes WSPRecv to be called 3 times :((. I need to modify several parts of this response, but since it comes in 3 slices, it is pretty hard to modify it accordingly. And, maybe on other machines or under different conditions (such as high traffic) there would only be one sole WSPRecv call, or maybe 10 calls. What is the best way to work arround this (please no NDIS :D), and how to properly change the buffer (lpBuffers->buf) by increasing it ?
int WSPAPI
WSPRecv(
SOCKET s,
LPWSABUF lpBuffers,
DWORD dwBufferCount,
LPDWORD lpNumberOfBytesRecvd,
LPDWORD lpFlags,
LPWSAOVERLAPPED lpOverlapped,
LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
LPWSATHREADID lpThreadId,
LPINT lpErrno
)
{
LPWSAOVERLAPPEDPLUS ProviderOverlapped = NULL;
SOCK_INFO *SocketContext = NULL;
int ret = SOCKET_ERROR;
*lpErrno = NO_ERROR;
//
// Find our provider socket corresponding to this one
//
SocketContext = FindAndRefSocketContext(s, lpErrno);
if ( NULL == SocketContext )
{
dbgprint( "WSPRecv: FindAndRefSocketContext failed!" );
goto cleanup;
}
//
// Check for overlapped I/O
//
if ( NULL != lpOverlapped )
{
/*bla bla .. not interesting in my case*/
}
else
{
ASSERT( SocketContext->Provider->NextProcTable.lpWSPRecv );
SetBlockingProvider(SocketContext->Provider);
ret = SocketContext->Provider->NextProcTable.lpWSPRecv(
SocketContext->ProviderSocket,
lpBuffers,
dwBufferCount,
lpNumberOfBytesRecvd,
lpFlags,
lpOverlapped,
lpCompletionRoutine,
lpThreadId,
lpErrno);
SetBlockingProvider(NULL);
//is this the place to modify packet length and contents ?
if (strstr(lpBuffers->buf, "var mapObj = null;"))
{
int nLen = strlen(lpBuffers->buf) + 200;
/*CHAR *szNewBuf = new CHAR[];
CHAR *pIndex;
pIndex = strstr(lpBuffers->buf, "var mapObj = null;");
nLen = strlen(strncpy(szNewBuf, lpBuffers->buf, (pIndex - lpBuffers->buf) * sizeof (CHAR)));
nLen = strlen(strncpy(szNewBuf + nLen * sizeof(CHAR), "var com = null;\r\n", 17 * sizeof(CHAR)));
pIndex += 18 * sizeof(CHAR);
nLen = strlen(strncpy(szNewBuf + nLen * sizeof(CHAR), pIndex, 1330 * sizeof (CHAR)));
nLen = strlen(strncpy(szNewBuf + nLen * sizeof(CHAR), "if (com == null)\r\n" \
"com = new ActiveXObject(\"InterCommJS.Gateway\");\r\n" \
"com.lat = latitude;\r\n" \
"com.lon = longitude;\r\n}", 111 * sizeof (CHAR)));
pIndex = strstr(szNewBuf, "Content-Length:");
pIndex += 16 * sizeof(CHAR);
strncpy(pIndex, "1465", 4 * sizeof(CHAR));
lpBuffers->buf = szNewBuf;
lpBuffers->len += 128;*/
}
if ( SOCKET_ERROR != ret )
{
SocketContext->BytesRecv += *lpNumberOfBytesRecvd;
}
}
cleanup:
if ( NULL != SocketContext )
DerefSocketContext( SocketContext, lpErrno );
return ret;
}
Thank you
my comment worked out. http response headers / request turned out to end in \r\n\r\n.