0

I want to be able to use the following function defined in a shared object file (lib.so) :

int encrypt_data (char* buffer_in, int size_in, char** buffer_out, int* size_out)

Basically, i want to be able to pass the content of a file to this function (buffer_in) and write the output content (buffer_out) into another file. Here is what i've tried so far :

PROCEDURE encrypt_data EXTERNAL  "lib.so" CDECL :
    DEFINE INPUT PARAMETER buffer_in        AS MEMPTR.
    DEFINE INPUT PARAMETER size_in          AS LONG.
    DEFINE OUTPUT PARAMETER buffer_out      AS MEMPTR.
    DEFINE OUTPUT PARAMETER size_out        AS LONG.
    DEFINE RETURN PARAMETER returnvalue     AS LONG.
END PROCEDURE.

PROCEDURE pi_encryptHash:
    DEFINE INPUT  PARAMETER ipc_fullPathToEncrypt  AS CHARACTER   NO-UNDO.
    DEFINE VARIABLE lm_bufferIn            AS MEMPTR    NO-UNDO.
    DEFINE VARIABLE li_sizeIn              AS INT       NO-UNDO.
    DEFINE VARIABLE lm_bufferFakeOut            AS MEMPTR    NO-UNDO.
    DEFINE VARIABLE lm_bufferOut            AS MEMPTR    NO-UNDO.
    DEFINE VARIABLE li_sizeOut             AS INT       NO-UNDO.
    DEFINE VARIABLE li_returnedCode          AS INTEGER NO-UNDO.

    /* make sure MEMPTR is sized correctly */
    FILE-INFO:FILE-NAME = ipc_fullPathToEncrypt.
    SET-SIZE(lm_bufferIn) = FILE-INFO:FILE-SIZE.
    li_sizeIn = GET-SIZE(lm_bufferIn).

    /* the actual read */
    INPUT FROM VALUE(ipc_fullPathToEncrypt) BINARY NO-MAP NO-CONVERT.
    IMPORT lm_bufferIn.
    INPUT CLOSE.

    /* Call the encrypt proc a first time to get the output lenght */
    SET-SIZE(lm_bufferFakeOut) = 2.
    RUN encrypt_data(INPUT lm_bufferIn, INPUT li_sizeIn, OUTPUT lm_bufferFakeOut, OUTPUT li_sizeOut, OUTPUT li_returnedCode).

    /* Call it a second time with a buffer large enough to get the output value */
    SET-SIZE(lm_bufferOut) = li_sizeOut.
    RUN encrypt_data(INPUT lm_bufferIn, INPUT li_sizeIn, OUTPUT lm_bufferOut, OUTPUT li_sizeOut, OUTPUT li_returnedCode).

    /* Write MEMPTR to file */
    OUTPUT TO VALUE(ipc_fullPathToEncrypt + ".sha") BINARY NO-MAP NO-CONVERT.
    EXPORT lm_bufferOut.
    OUTPUT CLOSE.

    SET-SIZE(lm_bufferIn) = 0.
    SET-SIZE(lm_bufferOut) = 0.

    DISPLAY li_returnedCode.

    RETURN "".

END PROCEDURE.

I think my problem is that i can't read the data of char** buffer_out, from what i understand it is a pointer to a pointer so what i'm really exporting here EXPORT lm_bufferOut. is the pointer address of the data i would like to export? But how can i export the data instead?

Tom Bascom
  • 13,405
  • 2
  • 27
  • 33
Greenzest
  • 75
  • 3

2 Answers2

2

Maybe not an answer to your original question but be aware that there are built functions in Progress for encryption. For instance you can do like this (in this example the encrypted value is base64-encoded so the result is "viewable"):

DEFINE VARIABLE cClearText      AS CHARACTER NO-UNDO.
DEFINE VARIABLE rBinaryKey      AS RAW       NO-UNDO.
DEFINE VARIABLE rEncryptedValue AS RAW       NO-UNDO.
DEFINE VARIABLE cEncryptedText  AS CHARACTER NO-UNDO.
DEFINE VARIABLE cDecryptedText  AS CHARACTER NO-UNDO.

ASSIGN
    cClearText = "This is the clear text string to be encrypted.".

MESSAGE "Original message: " cCleartext
    VIEW-AS ALERT-BOX INFO BUTTONS OK.

ASSIGN 
    SECURITY-POLICY:SYMMETRIC-ENCRYPTION-ALGORITHM = "AES_OFB_256"
    rBinaryKey = GENERATE-RANDOM-KEY
    SECURITY-POLICY:SYMMETRIC-ENCRYPTION-KEY = rBinaryKey
    SECURITY-POLICY:SYMMETRIC-ENCRYPTION-IV = ?
    rEncryptedValue = Encrypt (cClearText)
    cEncryptedText = BASE64-ENCODE(rEncryptedValue)
    .

MESSAGE "Encrypted Message:" cEncryptedText
    VIEW-AS ALERT-BOX INFO BUTTONS OK.

ASSIGN
    SECURITY-POLICY:SYMMETRIC-ENCRYPTION-KEY = rBinaryKey
    cDecryptedText = GET-STRING(DECRYPT (rEncryptedValue),1).

MESSAGE "Decrypted Message: " cDecryptedText
    VIEW-AS ALERT-BOX INFO BUTTONS OK.

This example is based on this knowledge base entry.

You can do:

MESSAGE SECURITY-POLICY:SYMMETRIC-SUPPORT VIEW-AS ALERT-BOX.

to see supported symmetric encryption algorithms supported.

Here's an SO question regarding different versions of AES algorithms:

How to choose an AES encryption mode (CBC ECB CTR OCB CFB)?

Community
  • 1
  • 1
Jensd
  • 7,886
  • 2
  • 28
  • 37
  • Thank you for answering me Jensd, i was aware that those built in functions exist but my client has its own encryption algo and i need to use it. If i can't figure out a solution to interface correctly with his lib i will make sure to check out your solution. – Greenzest Jan 13 '16 at 13:11
0

A solution has been found, below is the program used :

PROCEDURE pi_encryptDecrypt:
    DEFINE INPUT  PARAMETER ipc_inputFile  AS CHARACTER   NO-UNDO.
    DEFINE INPUT  PARAMETER ipc_outputFile  AS CHARACTER   NO-UNDO.
    DEFINE INPUT  PARAMETER ipi_codeOp     AS INTEGER     NO-UNDO.

    DEFINE VARIABLE lm_bufferIn            AS MEMPTR    NO-UNDO.
    DEFINE VARIABLE li_sizeIn              AS INT       NO-UNDO.
    DEFINE VARIABLE lm_bufferFakeOut            AS MEMPTR    NO-UNDO.
    DEFINE VARIABLE lm_bufferOut            AS MEMPTR    NO-UNDO.
    DEFINE VARIABLE li_sizeOut             AS INT       NO-UNDO.
    DEFINE VARIABLE li_returnedCode          AS INTEGER NO-UNDO.
    define variable mtarget as memptr.

    /* make sure MEMPTR is sized correctly */
    FILE-INFO:FILE-NAME = ipc_inputFile.
    SET-SIZE(lm_bufferIn) = FILE-INFO:FILE-SIZE.
    li_sizeIn = GET-SIZE(lm_bufferIn).

    /* the actual read */
    copy-lob from file ipc_inputFile to lm_bufferIn.


    /* set a buffer large enough to get the output value */
    SET-SIZE(lm_bufferOut) = 8.

    if ipi_codeOp = 1 then
        RUN encrypt_data(INPUT lm_bufferIn, INPUT li_sizeIn, OUTPUT lm_bufferOut, OUTPUT li_sizeOut, OUTPUT li_returnedCode).
    else
        RUN decrypt_data(INPUT lm_bufferIn, INPUT li_sizeIn, OUTPUT lm_bufferOut, OUTPUT li_sizeOut, OUTPUT li_returnedCode).

    set-size(mtarget) = li_sizeOut.
    SET-POINTER-VALUE(mtarget) = GET-INT64(lm_bufferOut, 1).


    /* Write MEMPTR to file */
    os-delete value(ipc_outputFile).
    COPY-LOB FROM mtarget for /* FOR est SUPER IMPORTANT !! - ne pas enlever */ li_sizeOut TO FILE (ipc_outputFile).


    SET-SIZE(lm_bufferIn) = 0.
    SET-SIZE(lm_bufferOut) = 0.
    set-size(mtarget) = 0.

    /*DISPLAY li_returnedCode.
    DISPLAY li_sizeOut.*/

    RETURN "".
END PROCEDURE.

As i stated in my question, the problem was indeed that char** buffer_out returns a pointer to a pointer to the data in the memory.

The trick was to use a second MEMPTR (mtarget) that will point to the actual data, size it to be large enough with SET-SIZE and then sets it to the value of a particular memory location (using SET-POINTER-VALUE), which we get from GET-INT64(lm_bufferOut, 1).

Greenzest
  • 75
  • 3