midrange.com code scratchpad
Name:
CIPHER Service Program
Scriptlanguage:
Plain Text
Tabwidth:
4
Date:
10/25/2007 07:23:37 pm
IP:
Logged
Description:
Service program to encrypt/decrypt data using 128-bit AES
Code:
  1.      H/TITLE CIPHER - Module to encrypt and decrypt data
  2.      Hnomain
  3.       *****************************************************************
  4.       * RPG IV module CIPHER                                          *
  5.       * Author:      Matt Haas                                        *
  6.       * Description: Common functions to encrypt and decrypt data.    *
  7.       *                                                               *
  8.       *              This module can handle up to 65,520 bytes of     *
  9.       *              data. This is 15 bytes less than 64k. This size  *
  10.       *              was used because it is the maximun character     *
  11.       *              field size that falls on a 16 byte boundry.      *
  12.       *                                                               *
  13.       *              AES ciphers will operate of 16 byte blocks of    *
  14.       *              data. Padding will be added to ensure that a     *
  15.       *              full block of data is encrypted. What this       *
  16.       *              means is the return data size will be a multiple *
  17.       *              of 16 bytes (5 bytes in will be 16 bytes out,    *
  18.       *              17 bytes in will be 32 bytes out, etc...)        *
  19.       *                                                               *
  20.       *Mark Date MDY  User ID  Rel  Call #   Description              *
  21.       *---- --------  -------- ---- -------- ------------------------ *
  22.       *F993 05/25/05  TPCHAASM               Initial create.          *
  23.       *                                                               *
  24.       *****************************************************************
  25.  
  26.       /COPY JDECPY,#CIPHER
  27.  
  28.      DGenAESSalt       PR            16A
  29.  
  30.      Dcipher           PR                  extproc('_CIPHER')
  31.      D receiver                        *
  32.      D control                       96A   OPTIONS(*VARSIZE)
  33.      D source                          *
  34.  
  35.      DAES_Controls     DS
  36.      D FunctionID                     2A
  37.      D DataLen                        5U 0
  38.      D Operation                      1A
  39.      D Mode                           1A
  40.      D BlockLength                    3U 0
  41.      D MAClength                      3U 0
  42.      D InitVector                    32A
  43.      D Reserved                       7A
  44.      D KeyOption                      1A
  45.      D KeySchedulePtr                  *
  46.      D Key                           32A
  47.  
  48.      DKeySchedule      S           1088A
  49.      DOP_ENCRYPT       C                   const(x'00')
  50.      DOP_DECRYPT       C                   const(x'01')
  51.      DOP_MAC           C                   const(x'02')
  52.      DMODE_ECB         C                   const(x'00')
  53.      DMODE_CBC         C                   const(x'01')
  54.      DKEYOPT_SCHEDULE  C                   const(x'00')
  55.      DKEYOPT_16BYTE    C                   const(x'10')
  56.      DKEYOPT_24BYTE    C                   const(x'18')
  57.      DKEYOPT_32BYTE    C                   const(x'20')
  58.      DFUNCID_PRN       C                   const(x'0008')
  59.      DFUNCID_AES       C                   const(x'0015')
  60.      DBLOCK_LENGTH     C                   const(16)
  61.  
  62.       *//////////////////////////////////////////////////////////////*
  63.       * (Aes128bitEncrypt) Encrypt data using 128-bit AES            *
  64.       *//////////////////////////////////////////////////////////////*
  65.      PAes128bitEncrypt...
  66.      P                 B                   export
  67.       *--------------------------------------------------------------*
  68.      DAes128bitEncrypt...
  69.      D                 PI         65520A   varying
  70.      D Password                      16A   value
  71.      D ClearText                  65504A   varying value
  72.  
  73.      Dbuff_in          S             16A
  74.      Dbuff_out         S             16A
  75.      DNumChunks        S             10I 0
  76.      Dctr              S             10I 0
  77.      DStartPos         S             10I 0
  78.      DCipherText       S          65520A   varying
  79.      Dp_recv           S               *
  80.      DP_src            S               *
  81.      Dsalt             S             16A
  82.      DlastBlock        S             16A   varying
  83.  
  84.       /free
  85.  
  86.           salt = GenAESSalt();
  87.  
  88.           // Encrypt using 128-bit AES, 16 byte chunks
  89.           AES_Controls = *ALLx'00';
  90.           FunctionID = FUNCID_AES;
  91.           DataLen = BLOCK_LENGTH;
  92.           Operation = OP_ENCRYPT;
  93.           Mode = MODE_CBC;
  94.           BlockLength = BLOCK_LENGTH;
  95.           KeyOption = KEYOPT_16BYTE;
  96.           KeySchedulePtr = %addr(KeySchedule);
  97.           Key = Password;
  98.           InitVector = salt;
  99.  
  100.           p_recv = %addr(buff_out);
  101.           p_src  = %addr(buff_in);
  102.  
  103.           // Pad the clear text
  104.           NumChunks = %len(ClearText) / BLOCK_LENGTH;
  105.  
  106.           //    If the length of the clear text is an exact
  107.           //    multiple of the block size, we need to subtract
  108.           //    1 from NumChunks to get the last BLOCK_SIZE
  109.           //    bytes of the data.
  110.           If %len(ClearText) = (NumChunks * BLOCK_LENGTH);
  111.               NumChunks = NumChunks - 1;
  112.           EndIf;
  113.           lastBlock = %subst(ClearText: (NumChunks * BLOCK_LENGTH) + 1);
  114.  
  115.           // Replace the last block of clear text with the padded value
  116.           ClearText = %subst(ClearText: 1 : (NumChunks * BLOCK_LENGTH))
  117.                     + AddPKCS5Padding(lastBlock);
  118.  
  119.           // Determine how many 16 byte blocks need encrypted
  120.           NumChunks = %len(ClearText) / BLOCK_LENGTH;
  121.           If (NumChunks * BLOCK_LENGTH) < %len(ClearText);
  122.              NumChunks = NumChunks + 1;
  123.           EndIf;
  124.  
  125.           StartPos = 1;
  126.           %len(CipherText) = 0;
  127.  
  128.           // Encrypt the passed in data
  129.           For ctr = 1 to NumChunks;
  130.              // If we're doing the last part of the clear text,
  131.              // we need to make sure it's padded out to 16 bytes
  132.              // with the padding character passed in.
  133.              If ctr = NumChunks;
  134.                 If (StartPos + BLOCK_LENGTH) > %len(ClearText);
  135.                    buff_in = %subst(ClearText: StartPos);
  136.                 Else;
  137.                    buff_in = %subst(ClearText: StartPos: BLOCK_LENGTH);
  138.                 EndIf;
  139.              Else;
  140.                 buff_in = %subst(ClearText: StartPos: BLOCK_LENGTH);
  141.              EndIf;
  142.              cipher( p_recv: AES_Controls: p_src);
  143.              CipherText = CipherText + buff_out;
  144.              StartPos = StartPos + BLOCK_LENGTH;
  145.              KeyOption = KEYOPT_SCHEDULE;
  146.           EndFor;
  147.  
  148.           // Add the salt to the CipherText
  149.           CipherText = salt + CipherText;
  150.  
  151.           return CipherText;
  152.       /end-free
  153.  
  154.      PAes128bitEncrypt...
  155.      P                 E
  156.  
  157.  
  158.       *//////////////////////////////////////////////////////////////*
  159.       * (Aes128bitDecrypt) Decrypt data using 128-bit AES            *
  160.       *//////////////////////////////////////////////////////////////*
  161.      PAes128bitDecrypt...
  162.      P                 B                   export
  163.       *--------------------------------------------------------------*
  164.      DAes128bitDecrypt...
  165.      D                 PI         65504A   varying
  166.      D Password                      16A   value
  167.      D CipherText                 65520A   varying value
  168.  
  169.      Dbuff_in          S             16A
  170.      Dbuff_out         S             16A
  171.      DNumChunks        S             10I 0
  172.      Dctr              S             10I 0
  173.      DStartPos         S             10I 0
  174.      DCipherWork       S          65520A   varying
  175.      DClearText        S          65520A   varying
  176.      Dp_recv           S               *
  177.      DP_src            S               *
  178.      DCipherTextLen    S             10I 0
  179.  
  180.       /free
  181.           // Decrypt using 128-bit AES, 16 byte chunks
  182.           AES_Controls = *ALLx'00';
  183.           FunctionID = FUNCID_AES;
  184.           DataLen = BLOCK_LENGTH;
  185.           Operation = OP_DECRYPT;
  186.           Mode = MODE_CBC;
  187.           BlockLength = BLOCK_LENGTH;
  188.           KeyOption = KEYOPT_16BYTE;
  189.           KeySchedulePtr = %addr(KeySchedule);
  190.           Key = Password;
  191.  
  192.           // First 16 bytes contains the salt
  193.           InitVector = %subst(CipherText: 1: 16);
  194.  
  195.           // Remove the salt from CipherText
  196.           CipherWork = %subst(CipherText: 17);
  197.  
  198.           p_recv = %addr(buff_out);
  199.           p_src  = %addr(buff_in);
  200.  
  201.           // Determine how many 16 byte blocks need decrypted
  202.           NumChunks = %len(CipherWork) / BLOCK_LENGTH;
  203.           If (NumChunks * BLOCK_LENGTH) < %len(CipherWork);
  204.              NumChunks = NumChunks + 1;
  205.           EndIf;
  206.  
  207.           StartPos = 1;
  208.           %len(ClearText) = 0;
  209.  
  210.           For ctr = 1 to NumChunks;
  211.              buff_in = %subst(CipherWork: StartPos: BLOCK_LENGTH);
  212.              cipher( p_recv: AES_Controls: p_src);
  213.              If (ctr = NumChunks);
  214.                 buff_out = RemovePKCS5Padding(buff_out);
  215.              EndIf;
  216.              ClearText = ClearText + buff_out;
  217.              StartPos = StartPos + BLOCK_LENGTH;
  218.              KeyOption = KEYOPT_SCHEDULE;
  219.           EndFor;
  220.  
  221.           return %trimr(ClearText);
  222.       /end-free
  223.  
  224.      PAes128bitDecrypt...
  225.      P                 E
  226.  
  227.       *//////////////////////////////////////////////////////////////*
  228.       * (RemovePKCS5Padding) Remove padding characters using the     *
  229.       *                      PKCS5 method.                           *
  230.       *//////////////////////////////////////////////////////////////*
  231.      PRemovePKCS5Padding...
  232.      P                 B                   export
  233.       *--------------------------------------------------------------*
  234.      DRemovePKCS5Padding...
  235.      D                 PI            16A   varying
  236.      D paddedBlock                   16A
  237.  
  238.      DpadCheck         C                   const(x'0102030405060708090A0B0C0D0E-
  239.      D                                     0F10')
  240.  
  241.      DpadChar          S              1A
  242.      DnumPadChars      S             10I 0
  243.      DunPadded         S             16A   varying
  244.  
  245.       /free
  246.           // padChar will give us the hex representation of
  247.           // how many characters to strip off the decyphered
  248.           // text. For example, if padChar = x'10', we need to
  249.           // remove all 16 characters from the decoded text
  250.           // since 10 is the hex value of 16
  251.  
  252.           padChar= %subst(paddedBlock: BLOCK_LENGTH: 1);
  253.           numPadChars = %scan(padChar: padCheck);
  254.  
  255.           Select;
  256.              When numPadChars = 16;
  257.                 %len(unPadded) = 0;
  258.              When numPadChars > 0 and numPadChars < 16;
  259.                 unPadded = %subst(paddedBlock: 1 :BLOCK_LENGTH - numPadChars);
  260.              Other;
  261.                 unPadded = paddedBlock;
  262.           EndSl;
  263.  
  264.           return unPadded;
  265.       /end-free
  266.  
  267.      PRemovePKCS5Padding...
  268.      P                 E
  269.  
  270.       *//////////////////////////////////////////////////////////////*
  271.       * (AddPKCS5Padding) Adds padding characters using the PKCS5    *
  272.       *                   method.                                    *
  273.       *//////////////////////////////////////////////////////////////*
  274.      PAddPKCS5Padding  B                   export
  275.       *--------------------------------------------------------------*
  276.      DAddPKCS5Padding  PI            32A   varying
  277.      D inBlock                       16A   varying
  278.  
  279.      DpadChars         C                   const(x'0102030405060708090A0B0C0D0E-
  280.      D                                     0F10')
  281.  
  282.      DpadChar          S              1A
  283.      Dpadded           S             32A   varying
  284.      DpadCharsNeeded   S             10I 0
  285.      Dctr              S             10I 0
  286.  
  287.       /free
  288.           padded = inBlock;
  289.  
  290.           // Determine how many padding bytes to add. For full blocks,
  291.           // add 16 bytes of padding.
  292.           padCharsNeeded = 16 - %len(inBlock);
  293.           If padCharsNeeded = 0;
  294.              padCharsNeeded = 16;
  295.           EndIf;
  296.  
  297.           padChar = %subst(padChars: padCharsNeeded: 1);
  298.  
  299.           For ctr = 1 to padCharsNeeded;
  300.               padded = padded + padChar;
  301.           EndFor;
  302.  
  303.           return padded;
  304.       /end-free
  305.  
  306.      PAddPKCS5Padding  E
  307.  
  308.       *//////////////////////////////////////////////////////////////*
  309.       * (GenAESSalt) Generate a 16 byte salt for use with AES.       *
  310.       *//////////////////////////////////////////////////////////////*
  311.      PGenAESSalt       B
  312.       *--------------------------------------------------------------*
  313.      DGenAESSalt       PI            16A
  314.  
  315.      DPRN_Controls     DS
  316.      D FunctionID                     2A
  317.      D SeedRequest                    1A
  318.      D Reserved1                      3A
  319.      D SeedLength                     5U 0
  320.      D PRNRequest                     1A
  321.      D PRNParity                      1A
  322.      D Reserved2                      4A
  323.      D NumberOfPRNs                   5U 0
  324.      D Reserverd3                    16A
  325.  
  326.      DNO_SEED          C                   const(x'00')
  327.      DADD_SEED         C                   const(x'01')
  328.      DGEN_REAL_PRN     C                   const(x'00')
  329.      DGEN_TEST_PRN     C                   const(x'01')
  330.      DNO_PARITY        C                   const(x'00')
  331.      DODD_PARITY       C                   const(x'01')
  332.      DEVEN_PARITY      C                   const(x'02')
  333.  
  334.      Dp_recv           S               *
  335.      DP_src            S               *
  336.      Dbuff_in          S             16A
  337.      Dbuff_out         S             16A
  338.  
  339.       /free
  340.           p_recv = %addr(buff_out);
  341.           p_src  = %addr(buff_in);
  342.  
  343.           //
  344.           // Setup CIPHER for a secure random number
  345.           //
  346.  
  347.           PRN_Controls = *ALLx'00';
  348.           FunctionID = FUNCID_PRN;
  349.           PRNRequest = GEN_REAL_PRN;
  350.           // NumberOfPRNs is the number of bytes to return.
  351.           NumberOfPRNs = 16;
  352.           PRNParity = NO_PARITY;
  353.  
  354.  
  355.           //
  356.           // Generate a secure random number
  357.           //
  358.  
  359.           cipher(p_recv: PRN_Controls: p_src);
  360.  
  361.           return buff_out;
  362.  
  363.       /end-free
  364.      PGenAESSalt       E
© 2004-2019 by midrange.com generated in 0.007s valid xhtml & css