Esempio n. 1
0
        /**
         * Derive an encryption key for a cipher contex key based on the raw password.
         *
         * If the raw key data is formated as x'hex' and there are exactly enough hex chars to fill
         * the key space (i.e 64 hex chars for a 256 bit key) then the key data will be used directly.
         *
         * Otherwise, a key data will be derived using PBKDF2
         *
         * returns SQLITE_OK if initialization was successful
         * returns SQLITE_NOMEM if the key could't be derived (for instance if pass is null or pass_sz is 0)
         */
        static int codec_key_derive(codec_ctx ctx, cipher_ctx c_ctx)
        {
            CODEC_TRACE("codec_key_derive: entered c_ctx.pass=%s, c_ctx.pass_sz=%d ctx.iv=%d ctx.iv_sz=%d c_ctx.kdf_iter=%d c_ctx.key_sz=%d\n",
                        c_ctx.pass, c_ctx.pass_sz, c_ctx.iv, c_ctx.iv_sz, c_ctx.key_sz);

            if (c_ctx.pass != null && c_ctx.pass_sz > 0)
            { // if pass is not null
                if ((c_ctx.pass_sz == (c_ctx.key_sz * 2) + 3) && c_ctx.pass.StartsWith("x'", StringComparison.InvariantCultureIgnoreCase))
                {
                    int    n = c_ctx.pass_sz - 3;       /* adjust for leading x' and tailing ' */
                    string z = c_ctx.pass.Substring(2); // + 2; /* adjust lead offset of x' */
                    CODEC_TRACE("codec_key_derive: deriving key from hex\n");
                    c_ctx.key = sqlite3HexToBlob(null, z, n);
                }
                else
                {
                    CODEC_TRACE("codec_key_derive: deriving key using AES256\n");

                    Rfc2898DeriveBytes k1 = new Rfc2898DeriveBytes(c_ctx.pass, c_ctx.iv, 2010);
                    c_ctx.key_sz = 32;
                    c_ctx.key    = k1.GetBytes(c_ctx.key_sz);
                }
#if NET_2_0
                Aes.BlockSize    = 0x80;
                Aes.FeedbackSize = 8;
                Aes.KeySize      = 0x100;
                Aes.Mode         = CipherMode.CBC;
#endif
                c_ctx.encryptor = Aes.CreateEncryptor(c_ctx.key, c_ctx.iv);
                c_ctx.decryptor = Aes.CreateDecryptor(c_ctx.key, c_ctx.iv);
                return(SQLITE_OK);
            }
            ;
            return(SQLITE_ERROR);
        }
Esempio n. 2
0
        /**
         * Derive an encryption key for a cipher contex key based on the raw password.
         *
         * If the raw key data is formated as x'hex' and there are exactly enough hex chars to fill
         * the key space (i.e 64 hex chars for a 256 bit key) then the key data will be used directly.
         *
         * Otherwise, a key data will be derived using PBKDF2
         *
         * returns SQLITE_OK if initialization was successful
         * returns SQLITE_NOMEM if the key could't be derived (for instance if pass is null or pass_sz is 0)
         */
        static int codec_key_derive(codec_ctx ctx, cipher_ctx c_ctx)
        {
            CODEC_TRACE("codec_key_derive: entered c_ctx.pass=%s, c_ctx.pass_sz=%d ctx.iv=%d ctx.iv_sz=%d c_ctx.kdf_iter=%d c_ctx.key_sz=%d\n",
                        c_ctx.pass, c_ctx.pass_sz, c_ctx.iv, c_ctx.iv_sz, c_ctx.key_sz);

            if (c_ctx.pass != null && c_ctx.pass_sz > 0)
            { // if pass is not null
                if ((c_ctx.pass_sz == (c_ctx.key_sz * 2) + 3) && sqlite3StrNICmp(c_ctx.pass, "x'", 2) == 0)
                {
                    int    n = c_ctx.pass_sz - 3;       /* adjust for leading x' and tailing ' */
                    string z = c_ctx.pass.Substring(2); // + 2; /* adjust lead offset of x' */
                    CODEC_TRACE("codec_key_derive: deriving key from hex\n");
                    c_ctx.key = sqlite3HexToBlob(null, z, n);
                }
                else
                {
                    CODEC_TRACE("codec_key_derive: deriving key using AES256\n");

                    Rfc2898DeriveBytes k1 = new Rfc2898DeriveBytes(c_ctx.pass, c_ctx.iv, 2010);
                    c_ctx.key_sz = 32;
                    c_ctx.key    = k1.GetBytes(c_ctx.key_sz);
                }
                c_ctx.encryptor = Aes.CreateEncryptor(c_ctx.key, c_ctx.iv);
                c_ctx.decryptor = Aes.CreateDecryptor(c_ctx.key, c_ctx.iv);
                return(SQLITE_OK);
            }
            ;
            return(SQLITE_ERROR);
        }
Esempio n. 3
0
 static void sqlite3FreeCodecArg(ref codec_ctx pCodecArg)
 {
     if (pCodecArg == null)
     {
         return;
     }
     codec_ctx_free(ref pCodecArg); // wipe and free allocated memory for the context
 }
Esempio n. 4
0
        /**
         * Free and wipe memory associated with a cipher_ctx, including the allocated
         * read_ctx and write_ctx.
         */
        static void codec_ctx_free(ref codec_ctx iCtx)
        {
            codec_ctx ctx = iCtx;

            CODEC_TRACE("codec_ctx_free: entered iCtx=%d\n", iCtx);
            cipher_ctx_free(ref ctx.read_ctx);
            cipher_ctx_free(ref ctx.write_ctx);
            iCtx = new codec_ctx();//codec_free(ctx, sizeof(codec_ctx);
        }
Esempio n. 5
0
 static void sqlite3pager_sqlite3PagerSetCodec(
     Pager pPager,
     dxCodec xCodec,
     dxCodecSizeChng xCodecSizeChng,
     dxCodecFree xCodecFree,
     codec_ctx pCodec
     )
 {
     sqlite3PagerSetCodec(pPager, xCodec, xCodecSizeChng, xCodecFree, pCodec);
 }
Esempio n. 6
0
        static int sqlite3CodecAttach(sqlite3 db, int nDb, string zKey, int nKey)
        {
            Db pDb = db.aDb[nDb];

            CODEC_TRACE("sqlite3CodecAttach: entered nDb=%d zKey=%s, nKey=%d\n", nDb, zKey, nKey);
            //activate_openssl();

            if (zKey != null && pDb.pBt != null)
            {
                Aes.KeySize = 256;
#if !SQLITE_SILVERLIGHT
                Aes.Padding = PaddingMode.None;
#endif
                codec_ctx ctx;
                int       rc;
                //Pager pPager = pDb.pBt.pBt.pPager;
                //sqlite3_file fd;

                ctx = new codec_ctx();//sqlite3Malloc(sizeof(codec_ctx);
                //if(ctx == null) return SQLITE_NOMEM;
                //memset(ctx, 0, sizeof(codec_ctx); /* initialize all pointers and values to 0 */

                ctx.pBt = pDb.pBt; /* assign pointer to database btree structure */

                if ((rc = cipher_ctx_init(ref ctx.read_ctx)) != SQLITE_OK)
                {
                    return(rc);
                }
                if ((rc = cipher_ctx_init(ref ctx.write_ctx)) != SQLITE_OK)
                {
                    return(rc);
                }

                /* pre-allocate a page buffer of PageSize bytes. This will
                 * be used as a persistent buffer for encryption and decryption
                 * operations to avoid overhead of multiple memory allocations*/
                ctx.buffer = sqlite3MemMalloc(sqlite3BtreeGetPageSize(ctx.pBt));//sqlite3Malloc(sqlite3BtreeGetPageSize(ctx.pBt);
                //if(ctx.buffer == null) return SQLITE_NOMEM;

                /* allocate space for salt data. Then read the first 16 bytes header as the salt for the key derivation */
                ctx.read_ctx.iv_sz = FILE_HEADER_SZ;
                ctx.read_ctx.iv    = new byte[ctx.read_ctx.iv_sz];//sqlite3Malloc( ctx.iv_sz );

                Buffer.BlockCopy(Encoding.UTF8.GetBytes(SQLITE_FILE_HEADER), 0, ctx.read_ctx.iv, 0, FILE_HEADER_SZ);

                sqlite3pager_sqlite3PagerSetCodec(sqlite3BtreePager(pDb.pBt), sqlite3Codec, null, sqlite3FreeCodecArg, ctx);

                codec_set_cipher_name(db, nDb, CIPHER, 0);
                codec_set_pass_key(db, nDb, zKey, nKey, 0);
                cipher_ctx_copy(ctx.write_ctx, ctx.read_ctx);

                //sqlite3BtreeSetPageSize( ctx.pBt, sqlite3BtreeGetPageSize( ctx.pBt ), MAX_IV_LENGTH, 0 );
            }
            return(SQLITE_OK);
        }
Esempio n. 7
0
            public codec_ctx Copy()
            {
                codec_ctx c = new codec_ctx();

                c.mode_rekey = mode_rekey;
                c.buffer     = sqlite3MemMalloc(buffer.Length);
                c.pBt        = pBt;
                if (read_ctx != null)
                {
                    c.read_ctx = read_ctx.Copy();
                }
                if (write_ctx != null)
                {
                    c.write_ctx = write_ctx.Copy();
                }
                return(c);
            }
Esempio n. 8
0
        static void sqlite3CodecGetKey(sqlite3 db, int nDb, out string zKey, out int nKey)
        {
            Db pDb = db.aDb[nDb];

            CODEC_TRACE("sqlite3CodecGetKey: entered db=%d, nDb=%d\n", db, nDb);

            if (pDb.pBt != null)
            {
                codec_ctx ctx = null;
                sqlite3pager_get_codec(pDb.pBt.pBt.pPager, ref ctx);

                if (ctx != null)
                { /* if the codec has an attached codec_context user the raw key data */
                    zKey = ctx.read_ctx.pass;
                    nKey = ctx.read_ctx.pass_sz;
                    return;
                }
            }
            zKey = null;
            nKey = 0;
        }
Esempio n. 9
0
        static int codec_set_pass_key(sqlite3 db, int nDb, string zKey, int nKey, int for_ctx)
        {
            Db pDb = db.aDb[nDb];

            CODEC_TRACE("codec_set_pass_key: entered db=%d nDb=%d cipher_name=%s nKey=%d for_ctx=%d\n", db, nDb, zKey, nKey, for_ctx);
            if (pDb.pBt != null)
            {
                codec_ctx  ctx = null;
                cipher_ctx c_ctx;
                sqlite3pager_get_codec(pDb.pBt.pBt.pPager, ref ctx);
                c_ctx = for_ctx != 0 ? ctx.write_ctx : ctx.read_ctx;

                cipher_ctx_set_pass(c_ctx, zKey, nKey);
                c_ctx.derive_key = true;

                if (for_ctx == 2)
                {
                    cipher_ctx_copy(for_ctx != 0 ? ctx.read_ctx : ctx.write_ctx, c_ctx);
                }
                return(SQLITE_OK);
            }
            return(SQLITE_ERROR);
        }
Esempio n. 10
0
        /**
         *
         * when for_ctx == 0 then it will change for read
         * when for_ctx == 1 then it will change for write
         * when for_ctx == 2 then it will change for both
         */
        private static int codec_set_cipher_name(sqlite3 db, int nDb, string cipher_name, int for_ctx)
        {
            var pDb = db.aDb[nDb];

            CODEC_TRACE("codec_set_cipher_name: entered db=%d nDb=%d cipher_name=%s for_ctx=%d\n", db, nDb, cipher_name, for_ctx);

            if (pDb.pBt != null)
            {
                codec_ctx  ctx = null;
                cipher_ctx c_ctx;
                sqlite3pager_get_codec(pDb.pBt.pBt.pPager, ref ctx);
                c_ctx = for_ctx != 0 ? ctx.write_ctx : ctx.read_ctx;

                c_ctx.derive_key = true;

                if (for_ctx == 2)
                {
                    cipher_ctx_copy(for_ctx != 0 ? ctx.read_ctx : ctx.write_ctx, c_ctx);
                }
                return(SQLITE_OK);
            }
            return(SQLITE_ERROR);
        }
Esempio n. 11
0
        /* sqlite3_rekey
        ** Given a database, this will reencrypt the database using a new key.
        ** There are two possible modes of operation. The first is rekeying
        ** an existing database that was not previously encrypted. The second
        ** is to change the key on an existing database.
        **
        ** The proposed logic for this function follows:
        ** 1. Determine if there is already a key present
        ** 2. If there is NOT already a key present, create one and attach a codec (key would be null)
        ** 3. Initialize a ctx.rekey parameter of the codec
        **
        ** Note: this will require modifications to the sqlite3Codec to support rekey
        **
        */
        public static int sqlite3_rekey(sqlite3 db, string pKey, int nKey)
        {
            CODEC_TRACE("sqlite3_rekey: entered db=%d pKey=%s, nKey=%d\n", db, pKey, nKey);
            //activate_openssl();
            if (db != null && pKey != null)
            {
                Db pDb = db.aDb[0];
                CODEC_TRACE("sqlite3_rekey: database pDb=%d\n", pDb);
                if (pDb.pBt != null)
                {
                    codec_ctx ctx = null;
                    int       rc;
                    Pgno      page_count = 0;
                    Pgno      pgno;
                    PgHdr     page   = null;
                    Pager     pPager = pDb.pBt.pBt.pPager;

                    sqlite3pager_get_codec(pDb.pBt.pBt.pPager, ref ctx);

                    if (ctx == null)
                    {
                        CODEC_TRACE("sqlite3_rekey: no codec attached to db, attaching now\n");
                        /* there was no codec attached to this database,so attach one now with a null password */
                        sqlite3CodecAttach(db, 0, pKey, nKey);
                        sqlite3pager_get_codec(pDb.pBt.pBt.pPager, ref ctx);

                        /* prepare this setup as if it had already been initialized */
                        Buffer.BlockCopy(Encoding.UTF8.GetBytes(SQLITE_FILE_HEADER), 0, ctx.read_ctx.iv, 0, FILE_HEADER_SZ);
                        ctx.read_ctx.key_sz = ctx.read_ctx.iv_sz = ctx.read_ctx.pass_sz = 0;
                    }

                    //if ( ctx.read_ctx.iv_sz != ctx.write_ctx.iv_sz )
                    //{
                    //  string error = "";
                    //  CODEC_TRACE( "sqlite3_rekey: updating page size for iv_sz change from %d to %d\n", ctx.read_ctx.iv_sz, ctx.write_ctx.iv_sz );
                    //  db.nextPagesize = sqlite3BtreeGetPageSize( pDb.pBt );
                    //  pDb.pBt.pBt.pageSizeFixed = false; /* required for sqlite3BtreeSetPageSize to modify pagesize setting */
                    //  sqlite3BtreeSetPageSize( pDb.pBt, db.nextPagesize, MAX_IV_LENGTH, 0 );
                    //  sqlite3RunVacuum( ref error, db );
                    //}

                    codec_set_pass_key(db, 0, pKey, nKey, 1);
                    ctx.mode_rekey = 1;

                    /* do stuff here to rewrite the database
                    ** 1. Create a transaction on the database
                    ** 2. Iterate through each page, reading it and then writing it.
                    ** 3. If that goes ok then commit and put ctx.rekey into ctx.key
                    ** note: don't deallocate rekey since it may be used in a subsequent iteration
                    */
                    rc = sqlite3BtreeBeginTrans(pDb.pBt, 1); /* begin write transaction */
                    sqlite3PagerPagecount(pPager, out page_count);
                    for (pgno = 1; rc == SQLITE_OK && pgno <= page_count; pgno++)
                    {     /* pgno's start at 1 see pager.c:pagerAcquire */
                        if (0 == sqlite3pager_is_mj_pgno(pPager, pgno))
                        { /* skip this page (see pager.c:pagerAcquire for reasoning) */
                            rc = sqlite3PagerGet(pPager, pgno, ref page);
                            if (rc == SQLITE_OK)
                            { /* write page see pager_incr_changecounter for example */
                                rc = sqlite3PagerWrite(page);
                                //printf("sqlite3PagerWrite(%d)\n", pgno);
                                if (rc == SQLITE_OK)
                                {
                                    sqlite3PagerUnref(page);
                                }
                            }
                        }
                    }

                    /* if commit was successful commit and copy the rekey data to current key, else rollback to release locks */
                    if (rc == SQLITE_OK)
                    {
                        CODEC_TRACE("sqlite3_rekey: committing\n");
                        db.nextPagesize = sqlite3BtreeGetPageSize(pDb.pBt);
                        rc = sqlite3BtreeCommit(pDb.pBt);
                        if (ctx != null)
                        {
                            cipher_ctx_copy(ctx.read_ctx, ctx.write_ctx);
                        }
                    }
                    else
                    {
                        CODEC_TRACE("sqlite3_rekey: rollback\n");
                        sqlite3BtreeRollback(pDb.pBt);
                    }

                    ctx.mode_rekey = 0;
                }
                return(SQLITE_OK);
            }
            return(SQLITE_ERROR);
        }
Esempio n. 12
0
/*
** Set or retrieve the codec for this pager
*/
    static void sqlite3PagerSetCodec(
    Pager pPager,
    dxCodec xCodec,                 //void *(*xCodec)(void*,void*,Pgno,int),
    dxCodecSizeChng xCodecSizeChng, //void (*xCodecSizeChng)(void*,int,int),
    dxCodecFree xCodecFree,         //void (*xCodecFree)(void*),
    codec_ctx pCodec
    )
    {
      if ( pPager.xCodecFree != null ) pPager.xCodecFree( ref pPager.pCodec );
      pPager.xCodec = (pPager.memDb!=0) ? null : xCodec;
      pPager.xCodecSizeChng = xCodecSizeChng;
      pPager.xCodecFree = xCodecFree;
      pPager.pCodec = pCodec;
      pagerReportSize( pPager );
    }
Esempio n. 13
0
 public codec_ctx Copy(  )
 {
   codec_ctx c = new codec_ctx();
   c.mode_rekey = mode_rekey;
   c.buffer = sqlite3MemMalloc( buffer.Length );
   c.pBt = pBt;
   if ( read_ctx != null ) c.read_ctx = read_ctx.Copy();
   if ( write_ctx != null ) c.write_ctx = write_ctx.Copy();
   return c;
 }
Esempio n. 14
0
        /*
         * sqlite3Codec can be called in multiple modes.
         * encrypt mode - expected to return a pointer to the
         * encrypted data without altering pData.
         * decrypt mode - expected to return a pointer to pData, with
         * the data decrypted in the input buffer
         */
        static byte[] sqlite3Codec(codec_ctx iCtx, byte[] data, Pgno pgno, int mode)
        {
            codec_ctx ctx    = (codec_ctx)iCtx;
            int       pg_sz  = sqlite3BtreeGetPageSize(ctx.pBt);
            int       offset = 0;

            byte[] pData = data;

            CODEC_TRACE("sqlite3Codec: entered pgno=%d, mode=%d, ctx.mode_rekey=%d, pg_sz=%d\n", pgno, mode, ctx.mode_rekey, pg_sz);

            /* derive key on first use if necessary */
            if (ctx.read_ctx.derive_key)
            {
                codec_key_derive(ctx, ctx.read_ctx);
                ctx.read_ctx.derive_key = false;
            }

            if (ctx.write_ctx.derive_key)
            {
                if (cipher_ctx_cmp(ctx.write_ctx, ctx.read_ctx) == 0)
                {
                    cipher_ctx_copy(ctx.write_ctx, ctx.read_ctx); // the relevant parameters are the same, just copy read key
                }
                else
                {
                    codec_key_derive(ctx, ctx.write_ctx);
                    ctx.write_ctx.derive_key = false;
                }
            }



            CODEC_TRACE("sqlite3Codec: switch mode=%d offset=%d\n", mode, offset);
            if (ctx.buffer.Length != pg_sz)
            {
                ctx.buffer = sqlite3MemMalloc(pg_sz);
            }
            switch (mode)
            {
            case SQLITE_DECRYPT:
                codec_cipher(ctx.read_ctx, pgno, CIPHER_DECRYPT, pg_sz, pData, ctx.buffer);
                if (pgno == 1)
                {
                    Buffer.BlockCopy(Encoding.UTF8.GetBytes(SQLITE_FILE_HEADER), 0, ctx.buffer, 0, FILE_HEADER_SZ); // memcpy( ctx.buffer, SQLITE_FILE_HEADER, FILE_HEADER_SZ ); /* copy file header to the first 16 bytes of the page */
                }
                Buffer.BlockCopy(ctx.buffer, 0, pData, 0, pg_sz);                                                   //memcpy( pData, ctx.buffer, pg_sz ); /* copy buffer data back to pData and return */
                return(pData);

            case SQLITE_ENCRYPT_WRITE_CTX: /* encrypt */
                if (pgno == 1)
                {
                    Buffer.BlockCopy(ctx.write_ctx.iv, 0, ctx.buffer, 0, FILE_HEADER_SZ);//memcpy( ctx.buffer, ctx.iv, FILE_HEADER_SZ ); /* copy salt to output buffer */
                }
                codec_cipher(ctx.write_ctx, pgno, CIPHER_ENCRYPT, pg_sz, pData, ctx.buffer);
                return(ctx.buffer); /* return persistent buffer data, pData remains intact */

            case SQLITE_ENCRYPT_READ_CTX:
                if (pgno == 1)
                {
                    Buffer.BlockCopy(ctx.read_ctx.iv, 0, ctx.buffer, 0, FILE_HEADER_SZ);//memcpy( ctx.buffer, ctx.iv, FILE_HEADER_SZ ); /* copy salt to output buffer */
                }
                codec_cipher(ctx.read_ctx, pgno, CIPHER_ENCRYPT, pg_sz, pData, ctx.buffer);
                return(ctx.buffer); /* return persistent buffer data, pData remains intact */

            default:
                return(pData);
            }
        }
Esempio n. 15
0
 static void sqlite3pager_sqlite3PagerSetCodec(
 Pager pPager,
 dxCodec xCodec,
 dxCodecSizeChng xCodecSizeChng,
 dxCodecFree xCodecFree,
 codec_ctx pCodec
 )
 {
   sqlite3PagerSetCodec( pPager, xCodec, xCodecSizeChng, xCodecFree, pCodec );
 }
Esempio n. 16
0
 /* BEGIN CRYPTO */
 static void sqlite3pager_get_codec( Pager pPager, ref codec_ctx ctx )
 {
   ctx = pPager.pCodec;
 }
Esempio n. 17
0
 /* BEGIN CRYPTO */
 static void sqlite3pager_get_codec(Pager pPager, ref codec_ctx ctx)
 {
     ctx = pPager.pCodec;
 }
Esempio n. 18
0
 /**
 * Free and wipe memory associated with a cipher_ctx, including the allocated
 * read_ctx and write_ctx.
 */
 static void codec_ctx_free( ref codec_ctx iCtx )
 {
   codec_ctx ctx = iCtx;
   CODEC_TRACE( "codec_ctx_free: entered iCtx=%d\n", iCtx );
   cipher_ctx_free( ref ctx.read_ctx );
   cipher_ctx_free( ref ctx.write_ctx );
   iCtx = new codec_ctx();//codec_free(ctx, sizeof(codec_ctx);
 }
Esempio n. 19
0
    /**
    * Derive an encryption key for a cipher contex key based on the raw password.
    *
    * If the raw key data is formated as x'hex' and there are exactly enough hex chars to fill
    * the key space (i.e 64 hex chars for a 256 bit key) then the key data will be used directly.
    *
    * Otherwise, a key data will be derived using PBKDF2
    *
    * returns SQLITE_OK if initialization was successful
    * returns SQLITE_NOMEM if the key could't be derived (for instance if pass is null or pass_sz is 0)
    */
    static int codec_key_derive( codec_ctx ctx, cipher_ctx c_ctx )
    {
      CODEC_TRACE( "codec_key_derive: entered c_ctx.pass=%s, c_ctx.pass_sz=%d ctx.iv=%d ctx.iv_sz=%d c_ctx.kdf_iter=%d c_ctx.key_sz=%d\n",
      c_ctx.pass, c_ctx.pass_sz, c_ctx.iv, c_ctx.iv_sz, c_ctx.key_sz );

      if ( c_ctx.pass != null && c_ctx.pass_sz > 0 )
      { // if pass is not null
        if ( ( c_ctx.pass_sz == ( c_ctx.key_sz * 2 ) + 3 ) && sqlite3StrNICmp( c_ctx.pass, "x'", 2 ) == 0 )
        {
          int n = c_ctx.pass_sz - 3; /* adjust for leading x' and tailing ' */
          string z = c_ctx.pass.Substring( 2 );// + 2; /* adjust lead offset of x' */
          CODEC_TRACE( "codec_key_derive: deriving key from hex\n" );
          c_ctx.key = sqlite3HexToBlob( null, z, n);
        }
        else
        {
          CODEC_TRACE( "codec_key_derive: deriving key using AES256\n" );

          Rfc2898DeriveBytes k1 = new Rfc2898DeriveBytes( c_ctx.pass, c_ctx.iv, 2010 );
          c_ctx.key_sz = 32;
          c_ctx.key = k1.GetBytes( c_ctx.key_sz );
        }
        c_ctx.encryptor = Aes.CreateEncryptor( c_ctx.key, c_ctx.iv );
        c_ctx.decryptor = Aes.CreateDecryptor( c_ctx.key, c_ctx.iv );
        return SQLITE_OK;
      };
      return SQLITE_ERROR;
    }
Esempio n. 20
0
        /*
         * sqlite3Codec can be called in multiple modes.
         * encrypt mode - expected to return a pointer to the
         * encrypted data without altering pData.
         * decrypt mode - expected to return a pointer to pData, with
         * the data decrypted in the input buffer
         */
        static byte[] sqlite3Codec(codec_ctx iCtx, byte[] data, Pgno pgno, int mode)
        {
            codec_ctx ctx    = (codec_ctx)iCtx;
            int       pg_sz  = sqlite3BtreeGetPageSize(ctx.pBt);
            int       offset = 0;

            byte[] pData = data;

            CODEC_TRACE("sqlite3Codec: entered pgno=%d, mode=%d, ctx.mode_rekey=%d, pg_sz=%d\n", pgno, mode, ctx.mode_rekey, pg_sz);

            /* derive key on first use if necessary */
            if (ctx.read_ctx.derive_key)
            {
                codec_key_derive(ctx, ctx.read_ctx);
                ctx.read_ctx.derive_key = false;
            }

            if (ctx.write_ctx.derive_key)
            {
                if (cipher_ctx_cmp(ctx.write_ctx, ctx.read_ctx) == 0)
                {
                    cipher_ctx_copy(ctx.write_ctx, ctx.read_ctx); // the relevant parameters are the same, just copy read key
                }
                else
                {
                    codec_key_derive(ctx, ctx.write_ctx);
                    ctx.write_ctx.derive_key = false;
                }
            }

            // bug from csharp project port
            // fix from original: https://github.com/sqlcipher/sqlcipher/blob/master/src/crypto.c

// original
// if(pgno == 1) offset = FILE_HEADER_SZ; /* adjust starting pointers in data page for header offset on first page*/

            CODEC_TRACE("sqlite3Codec: switch mode=%d offset=%d\n", mode, offset);
            if (ctx.buffer.Length != pg_sz)
            {
                ctx.buffer = sqlite3MemMalloc(pg_sz);
            }
            switch (mode)
            {
            case SQLITE_DECRYPT:
// original
//      if(pgno == 1) memcpy(buffer, SQLITE_FILE_HEADER, FILE_HEADER_SZ); /* copy file header to the first 16 bytes of the page */
//      rc = sqlcipher_page_cipher(ctx, CIPHER_READ_CTX, pgno, CIPHER_DECRYPT, page_sz - offset, pData + offset, (unsigned char*)buffer + offset);
//      if(rc != SQLITE_OK) sqlcipher_codec_ctx_set_error(ctx, rc);
//      memcpy(pData, buffer, page_sz); /* copy buffer data back to pData and return */
//      return pData;

// c-sharp project
//          codec_cipher( ctx.read_ctx, pgno, CIPHER_DECRYPT, pg_sz, pData, ctx.buffer );
//          if ( pgno == 1 )
//            Buffer.BlockCopy( Encoding.UTF8.GetBytes( SQLITE_FILE_HEADER ), 0, ctx.buffer, 0, FILE_HEADER_SZ );// memcpy( ctx.buffer, SQLITE_FILE_HEADER, FILE_HEADER_SZ ); /* copy file header to the first 16 bytes of the page */
//          Buffer.BlockCopy( ctx.buffer, 0, pData, 0, pg_sz ); //memcpy( pData, ctx.buffer, pg_sz ); /* copy buffer data back to pData and return */
//          return pData;

// my fix:
                if (pgno == 1)
                {
                    byte[] hdr = Encoding.UTF8.GetBytes(SQLITE_FILE_HEADER);
                    Buffer.BlockCopy(hdr, 0, ctx.buffer, 0, FILE_HEADER_SZ);// memcpy( ctx.buffer, SQLITE_FILE_HEADER, FILE_HEADER_SZ ); /* copy file header to the first 16 bytes of the page */
                    byte[] tmpOut  = new byte[pg_sz - FILE_HEADER_SZ];
                    byte[] tmpData = new byte[pg_sz - FILE_HEADER_SZ];
                    Buffer.BlockCopy(pData, FILE_HEADER_SZ, tmpData, 0, pg_sz - FILE_HEADER_SZ);
                    codec_cipher(ctx.read_ctx, pgno, CIPHER_DECRYPT, pg_sz - FILE_HEADER_SZ, tmpData, tmpOut);
                    Buffer.BlockCopy(tmpOut, 0, ctx.buffer, FILE_HEADER_SZ, pg_sz - FILE_HEADER_SZ);
                    Buffer.BlockCopy(ctx.buffer, 0, pData, 0, pg_sz);
                }
                else
                {
                    codec_cipher(ctx.read_ctx, pgno, CIPHER_DECRYPT, pg_sz, pData, ctx.buffer);
                    Buffer.BlockCopy(ctx.buffer, 0, pData, 0, pg_sz);
                }
                return(pData);

            case SQLITE_ENCRYPT_WRITE_CTX: /* encrypt */
// original
//      if(pgno == 1) memcpy(buffer, kdf_salt, FILE_HEADER_SZ); /* copy salt to output buffer */
//      rc = sqlcipher_page_cipher(ctx, CIPHER_WRITE_CTX, pgno, CIPHER_ENCRYPT, page_sz - offset, pData + offset, (unsigned char*)buffer + offset);
//      if(rc != SQLITE_OK) sqlcipher_codec_ctx_set_error(ctx, rc);
//      return buffer; /* return persistent buffer data, pData remains intact */

// c-sharp project
//          if ( pgno == 1 )
//            Buffer.BlockCopy( ctx.write_ctx.iv, 0, ctx.buffer, 0, FILE_HEADER_SZ );//memcpy( ctx.buffer, ctx.iv, FILE_HEADER_SZ ); /* copy salt to output buffer */
//          codec_cipher( ctx.write_ctx, pgno, CIPHER_ENCRYPT, pg_sz, pData, ctx.buffer );
//          return ctx.buffer; /* return persistent buffer data, pData remains intact */

// my fix
                if (pgno == 1)
                {
                    Buffer.BlockCopy(ctx.write_ctx.iv, 0, ctx.buffer, 0, FILE_HEADER_SZ);//memcpy( ctx.buffer, ctx.iv, FILE_HEADER_SZ ); /* copy salt to output buffer */
                    byte[] tmpOut  = new byte[pg_sz - FILE_HEADER_SZ];
                    byte[] tmpData = new byte[pg_sz - FILE_HEADER_SZ];
                    Buffer.BlockCopy(pData, FILE_HEADER_SZ, tmpData, 0, pg_sz - FILE_HEADER_SZ);
                    codec_cipher(ctx.write_ctx, pgno, CIPHER_ENCRYPT, pg_sz - FILE_HEADER_SZ, tmpData, tmpOut);
                    Buffer.BlockCopy(tmpOut, 0, ctx.buffer, FILE_HEADER_SZ, pg_sz - FILE_HEADER_SZ);
                }
                else
                {
                    codec_cipher(ctx.write_ctx, pgno, CIPHER_ENCRYPT, pg_sz, pData, ctx.buffer);
                }
                return(ctx.buffer); /* return persistent buffer data, pData remains intact */

            case SQLITE_ENCRYPT_READ_CTX:
// original
//      if(pgno == 1) memcpy(buffer, kdf_salt, FILE_HEADER_SZ); /* copy salt to output buffer */
//      rc = sqlcipher_page_cipher(ctx, CIPHER_READ_CTX, pgno, CIPHER_ENCRYPT, page_sz - offset, pData + offset, (unsigned char*)buffer + offset);
//      if(rc != SQLITE_OK) sqlcipher_codec_ctx_set_error(ctx, rc);
//      return buffer; /* return persistent buffer data, pData remains intact */

// c-sharp project
//	        if ( pgno == 1 )
//            Buffer.BlockCopy( ctx.read_ctx.iv, 0, ctx.buffer, 0, FILE_HEADER_SZ );//memcpy( ctx.buffer, ctx.iv, FILE_HEADER_SZ ); /* copy salt to output buffer */
//          codec_cipher( ctx.read_ctx, pgno, CIPHER_ENCRYPT, pg_sz, pData, ctx.buffer );
//          return ctx.buffer; /* return persistent buffer data, pData remains intact */
// my fix
                if (pgno == 1)
                {
                    Buffer.BlockCopy(ctx.read_ctx.iv, 0, ctx.buffer, 0, FILE_HEADER_SZ);//memcpy( ctx.buffer, ctx.iv, FILE_HEADER_SZ ); /* copy salt to output buffer */
                    byte[] tmpOut  = new byte[pg_sz - FILE_HEADER_SZ];
                    byte[] tmpData = new byte[pg_sz - FILE_HEADER_SZ];
                    Buffer.BlockCopy(pData, FILE_HEADER_SZ, tmpData, 0, pg_sz - FILE_HEADER_SZ);
                    codec_cipher(ctx.read_ctx, pgno, CIPHER_ENCRYPT, pg_sz - FILE_HEADER_SZ, tmpData, tmpOut);
                    Buffer.BlockCopy(tmpOut, 0, ctx.buffer, FILE_HEADER_SZ, pg_sz - FILE_HEADER_SZ);
                }
                else
                {
                    codec_cipher(ctx.read_ctx, pgno, CIPHER_ENCRYPT, pg_sz, pData, ctx.buffer);
                }
                return(ctx.buffer); /* return persistent buffer data, pData remains intact */

            default:
                return(pData);
            }
        }
Esempio n. 21
0
 static void sqlite3FreeCodecArg( ref codec_ctx pCodecArg )
 {
   if ( pCodecArg == null ) return;
   codec_ctx_free( ref pCodecArg ); // wipe and free allocated memory for the context
 }
Esempio n. 22
0
    static int sqlite3CodecAttach( sqlite3 db, int nDb, string zKey, int nKey )
    {
      Db pDb = db.aDb[nDb];

      CODEC_TRACE( "sqlite3CodecAttach: entered nDb=%d zKey=%s, nKey=%d\n", nDb, zKey, nKey );
      //activate_openssl();

      if ( zKey != null && pDb.pBt != null )
      {
        Aes.KeySize = 256;
#if !SQLITE_SILVERLIGHT
        Aes.Padding = PaddingMode.None;
#endif
        codec_ctx ctx;
        int rc;
        Pager pPager = pDb.pBt.pBt.pPager;
        sqlite3_file fd;

        ctx = new codec_ctx();//sqlite3Malloc(sizeof(codec_ctx);
        //if(ctx == null) return SQLITE_NOMEM;
        //memset(ctx, 0, sizeof(codec_ctx); /* initialize all pointers and values to 0 */

        ctx.pBt = pDb.pBt; /* assign pointer to database btree structure */

        if ( ( rc = cipher_ctx_init( ref ctx.read_ctx ) ) != SQLITE_OK ) return rc;
        if ( ( rc = cipher_ctx_init( ref ctx.write_ctx ) ) != SQLITE_OK ) return rc;

        /* pre-allocate a page buffer of PageSize bytes. This will
        be used as a persistent buffer for encryption and decryption
        operations to avoid overhead of multiple memory allocations*/
        ctx.buffer = sqlite3MemMalloc(sqlite3BtreeGetPageSize( ctx.pBt ));//sqlite3Malloc(sqlite3BtreeGetPageSize(ctx.pBt);
        //if(ctx.buffer == null) return SQLITE_NOMEM;

        /* allocate space for salt data. Then read the first 16 bytes header as the salt for the key derivation */
        ctx.read_ctx.iv_sz = FILE_HEADER_SZ;
        ctx.read_ctx.iv = new byte[ctx.read_ctx.iv_sz];//sqlite3Malloc( ctx.iv_sz );

        Buffer.BlockCopy( Encoding.UTF8.GetBytes( SQLITE_FILE_HEADER ), 0, ctx.read_ctx.iv, 0, FILE_HEADER_SZ );

        sqlite3pager_sqlite3PagerSetCodec( sqlite3BtreePager( pDb.pBt ), sqlite3Codec, null, sqlite3FreeCodecArg, ctx );

        codec_set_cipher_name( db, nDb, CIPHER, 0 );
        codec_set_pass_key( db, nDb, zKey, nKey, 0 );
        cipher_ctx_copy( ctx.write_ctx, ctx.read_ctx );

        //sqlite3BtreeSetPageSize( ctx.pBt, sqlite3BtreeGetPageSize( ctx.pBt ), MAX_IV_LENGTH, 0 );
      }
      return SQLITE_OK;
    }
Esempio n. 23
0
    /*
    * sqlite3Codec can be called in multiple modes.
    * encrypt mode - expected to return a pointer to the
    * encrypted data without altering pData.
    * decrypt mode - expected to return a pointer to pData, with
    * the data decrypted in the input buffer
    */
    static byte[] sqlite3Codec( codec_ctx iCtx, byte[] data, Pgno pgno, int mode )
    {
      codec_ctx ctx = (codec_ctx)iCtx;
      int pg_sz = sqlite3BtreeGetPageSize( ctx.pBt );
      int offset = 0;
      byte[] pData = data;

      CODEC_TRACE( "sqlite3Codec: entered pgno=%d, mode=%d, ctx.mode_rekey=%d, pg_sz=%d\n", pgno, mode, ctx.mode_rekey, pg_sz );

      /* derive key on first use if necessary */
      if ( ctx.read_ctx.derive_key )
      {
        codec_key_derive( ctx, ctx.read_ctx );
        ctx.read_ctx.derive_key = false;
      }

      if ( ctx.write_ctx.derive_key )
      {
        if ( cipher_ctx_cmp( ctx.write_ctx, ctx.read_ctx ) == 0 )
        {
          cipher_ctx_copy( ctx.write_ctx, ctx.read_ctx ); // the relevant parameters are the same, just copy read key
        }
        else
        {
          codec_key_derive( ctx, ctx.write_ctx );
          ctx.write_ctx.derive_key = false;
        }
      }



      CODEC_TRACE( "sqlite3Codec: switch mode=%d offset=%d\n", mode, offset );
      if ( ctx.buffer.Length != pg_sz ) ctx.buffer = sqlite3MemMalloc(pg_sz);
      switch ( mode )
      {
        case SQLITE_DECRYPT:
          codec_cipher( ctx.read_ctx, pgno, CIPHER_DECRYPT, pg_sz, pData,  ctx.buffer);
          if ( pgno == 1 ) Buffer.BlockCopy( Encoding.UTF8.GetBytes( SQLITE_FILE_HEADER ), 0, ctx.buffer, 0, FILE_HEADER_SZ );// memcpy( ctx.buffer, SQLITE_FILE_HEADER, FILE_HEADER_SZ ); /* copy file header to the first 16 bytes of the page */
          Buffer.BlockCopy( ctx.buffer, 0, pData, 0, pg_sz ); //memcpy( pData, ctx.buffer, pg_sz ); /* copy buffer data back to pData and return */
          return pData;
        case SQLITE_ENCRYPT_WRITE_CTX: /* encrypt */
          if ( pgno == 1 ) Buffer.BlockCopy( ctx.write_ctx.iv, 0, ctx.buffer, 0, FILE_HEADER_SZ );//memcpy( ctx.buffer, ctx.iv, FILE_HEADER_SZ ); /* copy salt to output buffer */
          codec_cipher( ctx.write_ctx, pgno, CIPHER_ENCRYPT, pg_sz, pData, ctx.buffer);
          return ctx.buffer; /* return persistent buffer data, pData remains intact */
        case SQLITE_ENCRYPT_READ_CTX:
          if ( pgno == 1 ) Buffer.BlockCopy( ctx.read_ctx.iv, 0, ctx.buffer, 0, FILE_HEADER_SZ );//memcpy( ctx.buffer, ctx.iv, FILE_HEADER_SZ ); /* copy salt to output buffer */
          codec_cipher( ctx.read_ctx, pgno, CIPHER_ENCRYPT, pg_sz, pData, ctx.buffer);
          return ctx.buffer; /* return persistent buffer data, pData remains intact */
        default:
          return pData;
      }
    }