~ubuntu-branches/ubuntu/wily/afnix/wily

« back to all changes in this revision

Viewing changes to src/mod/sec/shl/Rc2.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Anibal Monsalve Salazar
  • Date: 2011-03-16 21:31:18 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20110316213118-gk4k3ez3e5d2huna
Tags: 2.0.0-1
* QA upload.
* New upstream release
* Debian source format is 3.0 (quilt)
* Fix debhelper-but-no-misc-depends
* Fix ancient-standards-version
* Fix package-contains-linda-override
* debhelper compatibility is 7
* Fix dh-clean-k-is-deprecated

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// ---------------------------------------------------------------------------
 
2
// - Rc2.cpp                                                                 -
 
3
// - afnix:sec module - RC2 block cipher class implementation                -
 
4
// ---------------------------------------------------------------------------
 
5
// - This program is free software;  you can redistribute it  and/or  modify -
 
6
// - it provided that this copyright notice is kept intact.                  -
 
7
// -                                                                         -
 
8
// - This program  is  distributed in  the hope  that it will be useful, but -
 
9
// - without  any  warranty;  without  even   the   implied    warranty   of -
 
10
// - merchantability or fitness for a particular purpose.  In no event shall -
 
11
// - the copyright holder be liable for any  direct, indirect, incidental or -
 
12
// - special damages arising in any way out of the use of this software.     -
 
13
// ---------------------------------------------------------------------------
 
14
// - copyright (c) 1999-2011 amaury darsch                                   -
 
15
// ---------------------------------------------------------------------------
 
16
 
 
17
#include "Rc2.hpp"
 
18
#include "Vector.hpp"
 
19
#include "Integer.hpp"
 
20
#include "Cryptics.hxx"
 
21
#include "QuarkZone.hpp"
 
22
 
 
23
namespace afnix {
 
24
 
 
25
  // -------------------------------------------------------------------------
 
26
  // - private section                                                       -
 
27
  // -------------------------------------------------------------------------
 
28
 
 
29
  // RC2 block cipher constants
 
30
  static const char* RC2_ALGO_NAME = "RC2";
 
31
  static const long  RC2_BLOK_SIZE = 8;
 
32
  static const long  RC2_WORD_SIZE = RC2_BLOK_SIZE / 2;
 
33
 
 
34
  // RC2 valid key constants
 
35
  static const long  RC2_VKEY_BITS = 1024;                          
 
36
  static const long  RC2_VKEY_SIZE = RC2_VKEY_BITS / 8;
 
37
 
 
38
  // RC2 effective key constants
 
39
  static const long  RC2_EKEY_BITS = 1024;
 
40
  static const long  RC2_EKEY_SIZE = RC2_EKEY_BITS / 8;
 
41
  static const long  RC2_EKEY_WLEN = RC2_EKEY_SIZE / 2;
 
42
 
 
43
  // RC2 PI constant
 
44
  static t_byte RC2_PI[256]={
 
45
    0xd9, 0x78, 0xf9, 0xc4, 0x19, 0xdd, 0xb5, 0xed,
 
46
    0x28, 0xe9, 0xfd, 0x79, 0x4a, 0xa0, 0xd8, 0x9d,
 
47
    0xc6, 0x7e, 0x37, 0x83, 0x2b, 0x76, 0x53, 0x8e,
 
48
    0x62, 0x4c, 0x64, 0x88, 0x44, 0x8b, 0xfb, 0xa2,
 
49
    0x17, 0x9a, 0x59, 0xf5, 0x87, 0xb3, 0x4f, 0x13,
 
50
    0x61, 0x45, 0x6d, 0x8d, 0x09, 0x81, 0x7d, 0x32,
 
51
    0xbd, 0x8f, 0x40, 0xeb, 0x86, 0xb7, 0x7b, 0x0b,
 
52
    0xf0, 0x95, 0x21, 0x22, 0x5c, 0x6b, 0x4e, 0x82,
 
53
    0x54, 0xd6, 0x65, 0x93, 0xce, 0x60, 0xb2, 0x1c,
 
54
    0x73, 0x56, 0xc0, 0x14, 0xa7, 0x8c, 0xf1, 0xdc,
 
55
    0x12, 0x75, 0xca, 0x1f, 0x3b, 0xbe, 0xe4, 0xd1,
 
56
    0x42, 0x3d, 0xd4, 0x30, 0xa3, 0x3c, 0xb6, 0x26,
 
57
    0x6f, 0xbf, 0x0e, 0xda, 0x46, 0x69, 0x07, 0x57,
 
58
    0x27, 0xf2, 0x1d, 0x9b, 0xbc, 0x94, 0x43, 0x03,
 
59
    0xf8, 0x11, 0xc7, 0xf6, 0x90, 0xef, 0x3e, 0xe7,
 
60
    0x06, 0xc3, 0xd5, 0x2f, 0xc8, 0x66, 0x1e, 0xd7,
 
61
    0x08, 0xe8, 0xea, 0xde, 0x80, 0x52, 0xee, 0xf7,
 
62
    0x84, 0xaa, 0x72, 0xac, 0x35, 0x4d, 0x6a, 0x2a,
 
63
    0x96, 0x1a, 0xd2, 0x71, 0x5a, 0x15, 0x49, 0x74,
 
64
    0x4b, 0x9f, 0xd0, 0x5e, 0x04, 0x18, 0xa4, 0xec,
 
65
    0xc2, 0xe0, 0x41, 0x6e, 0x0f, 0x51, 0xcb, 0xcc,
 
66
    0x24, 0x91, 0xaf, 0x50, 0xa1, 0xf4, 0x70, 0x39,
 
67
    0x99, 0x7c, 0x3a, 0x85, 0x23, 0xb8, 0xb4, 0x7a,
 
68
    0xfc, 0x02, 0x36, 0x5b, 0x25, 0x55, 0x97, 0x31,
 
69
    0x2d, 0x5d, 0xfa, 0x98, 0xe3, 0x8a, 0x92, 0xae,
 
70
    0x05, 0xdf, 0x29, 0x10, 0x67, 0x6c, 0xba, 0xc9,
 
71
    0xd3, 0x00, 0xe6, 0xcf, 0xe1, 0x9e, 0xa8, 0x2c,
 
72
    0x63, 0x16, 0x01, 0x3f, 0x58, 0xe2, 0x89, 0xa9,
 
73
    0x0d, 0x38, 0x34, 0x1b, 0xab, 0x33, 0xff, 0xb0,
 
74
    0xbb, 0x48, 0x0c, 0x5f, 0xb9, 0xb1, 0xcd, 0x2e,
 
75
    0xc5, 0xf3, 0xdb, 0x47, 0xe5, 0xa5, 0x9c, 0x77,
 
76
    0x0a, 0xa6, 0x20, 0x68, 0xfe, 0x7f, 0xc1, 0xad
 
77
  };
 
78
 
 
79
  // this procedure expand the key into an effective key
 
80
  static void rc2_key_expand (t_word* rkey, const Key& key, const long klen) {
 
81
    // basic check as usual
 
82
    if (rkey == nilp) return;
 
83
    // check the supplied key size
 
84
    long blen = key.getsize ();
 
85
    if (blen >= RC2_EKEY_SIZE) {
 
86
      throw Exception ("key-error", "invalid key size");
 
87
    }
 
88
    // load the byte key
 
89
    t_byte bkey[RC2_EKEY_SIZE];
 
90
    for (long i = 0; i < blen; i++) bkey[i] = key.getbyte (i);
 
91
    // compute effective key length
 
92
    long t8 = (klen + 7) / 8;
 
93
    long te = 1 << (8 + klen - 8 * t8);
 
94
    t_byte tm = 0xFF % te;
 
95
    // key expansion first loop
 
96
    for (long i = blen; i < RC2_EKEY_SIZE; i++) {
 
97
      t_byte k = bkey[i-1] + bkey[i-blen];
 
98
      bkey[i] = RC2_PI[k];
 
99
    }
 
100
    bkey[RC2_EKEY_SIZE - t8] = RC2_PI[bkey[RC2_EKEY_SIZE - t8] & tm];
 
101
    // key expansion second loop
 
102
    for (long i = RC2_EKEY_SIZE - t8 - 1; i >= 0; i--) {
 
103
      bkey[i] = RC2_PI[bkey[i+1] ^ bkey[i+t8]];
 
104
    }
 
105
    // map the word key
 
106
    for (long i = 0, j = 0; i < RC2_EKEY_SIZE-1; i += 2, j++) {
 
107
      rkey[j] = bkey[i+1];
 
108
      rkey[j] <<= 8;
 
109
      rkey[j] |= bkey[i];
 
110
    }
 
111
  }
 
112
 
 
113
  // this procedure bind an input buffer to the state word
 
114
  static inline void rc2_bi_to_r (t_word* r, const t_byte* bi) {
 
115
    // check result and input buffer
 
116
    if ((r == nilp) || (bi == nilp)) return;
 
117
    // bind the word from the input bytes
 
118
    for (long i = 0, j = 0; i < RC2_BLOK_SIZE; i += 2, j++) {
 
119
      r[j] = bi[i+1];
 
120
      r[j] <<= 8;
 
121
      r[j] |= bi[i];
 
122
    }
 
123
  }
 
124
 
 
125
  // this procedure bind a state word to an output buffer
 
126
  static inline void rc2_r_to_bo (t_byte* bo, const t_word* r) {
 
127
    // check result and buffer
 
128
    if ((bo == nilp) || (r == nilp)) return;
 
129
    // bind the byte from the words
 
130
    for (long i = 0, j = 0; i < RC2_BLOK_SIZE; i += 2, j++) {
 
131
      bo[i]   = (t_byte) r[j];
 
132
      bo[i+1] = (t_byte) (r[j] >> 8);
 
133
    }
 
134
  }
 
135
 
 
136
  // this procedure do an encryption mix up
 
137
  static long rc2_enc_mix_up (t_word* r, const t_word* ekey, 
 
138
                              const long j, const long i) {
 
139
    // compute index
 
140
    long i1 = i - 1; long i2 = i - 2; long i3 = i - 3;
 
141
    if (i1 < 0) i1 += 4;
 
142
    if (i2 < 0) i2 += 4;
 
143
    if (i3 < 0) i3 += 4;
 
144
    r[i] = r[i] + ekey[j] + (r[i1] & r[i2]) + ((~r[i1]) & r[i3]);
 
145
    // compute rotation index
 
146
    long k =  (i == 0) ? 1 : (i == 1) ? 2 : (i == 2) ? 3 : 5;
 
147
    r[i] = wrotl (r[i], k);
 
148
    // update index result
 
149
    return j + 1;
 
150
  }
 
151
 
 
152
  // this procedure performs an encryption mixing round
 
153
  static long rc2_enc_mix (t_word* r, const t_word* ekey, const long j) {
 
154
    // mix up: 0
 
155
    long result = rc2_enc_mix_up (r, ekey, j, 0);
 
156
    // mix up: 1
 
157
    result = rc2_enc_mix_up (r, ekey, result, 1);
 
158
    // mix up: 2
 
159
    result = rc2_enc_mix_up (r, ekey, result, 2);
 
160
    // mix up: 3
 
161
    result = rc2_enc_mix_up (r, ekey, result, 3);
 
162
    // here it is
 
163
    return result;
 
164
  }
 
165
 
 
166
  // this procedure do an encryption mash up
 
167
  static void rc2_enc_mash_up (t_word* r, const t_word* ekey, const long i) {
 
168
    // compute index
 
169
    long i1 = i - 1;
 
170
    if (i1 < 0) i1 += 4;
 
171
    // compute mash up
 
172
    r[i] = r[i] + ekey[r[i1] & 63];
 
173
  }
 
174
 
 
175
  // this procedure performs an encryption mash round
 
176
  static void rc2_enc_mash (t_word* r, const t_word* ekey) {
 
177
    rc2_enc_mash_up (r, ekey, 0);
 
178
    rc2_enc_mash_up (r, ekey, 1);
 
179
    rc2_enc_mash_up (r, ekey, 2);
 
180
    rc2_enc_mash_up (r, ekey, 3);
 
181
  }
 
182
 
 
183
  // this procedure performs an encryption round
 
184
  static void rc2_enc (t_word* r, const t_word* ekey) {
 
185
    // 0: initialize index
 
186
    long j = 0;
 
187
    // 1: five mixing round
 
188
    j = rc2_enc_mix (r, ekey, j);
 
189
    j = rc2_enc_mix (r, ekey, j);
 
190
    j = rc2_enc_mix (r, ekey, j);
 
191
    j = rc2_enc_mix (r, ekey, j);
 
192
    j = rc2_enc_mix (r, ekey, j);
 
193
    // 2: one mashing round
 
194
    rc2_enc_mash (r, ekey);
 
195
    // 3: six mixing round
 
196
    j = rc2_enc_mix (r, ekey, j);
 
197
    j = rc2_enc_mix (r, ekey, j);
 
198
    j = rc2_enc_mix (r, ekey, j);
 
199
    j = rc2_enc_mix (r, ekey, j);
 
200
    j = rc2_enc_mix (r, ekey, j);
 
201
    j = rc2_enc_mix (r, ekey, j);
 
202
    // 4: one mashing round
 
203
    rc2_enc_mash (r, ekey);
 
204
    // 5: five mixing rounds
 
205
    j = rc2_enc_mix (r, ekey, j);
 
206
    j = rc2_enc_mix (r, ekey, j);
 
207
    j = rc2_enc_mix (r, ekey, j);
 
208
    j = rc2_enc_mix (r, ekey, j);
 
209
    j = rc2_enc_mix (r, ekey, j);
 
210
    // basic verififcation
 
211
    if (j != 64) {
 
212
      throw Exception ("internal-error", "invalid rc2 round index");
 
213
    }
 
214
  }
 
215
 
 
216
  // this procedure do a decryption mix up
 
217
  static long rc2_dec_mix_up (t_word* r, const t_word* ekey, 
 
218
                              const long j, const long i) {
 
219
    // compute rotation index
 
220
    long k =  (i == 0) ? 1 : (i == 1) ? 2 : (i == 2) ? 3 : 5;
 
221
    r[i] = wrotr (r[i], k);
 
222
    // compute index
 
223
    long i1 = i - 1; long i2 = i - 2; long i3 = i - 3;
 
224
    if (i1 < 0) i1 += 4;
 
225
    if (i2 < 0) i2 += 4;
 
226
    if (i3 < 0) i3 += 4;
 
227
    r[i] = r[i] - ekey[j] - (r[i1] & r[i2]) - ((~r[i1]) & r[i3]);
 
228
    // update index result
 
229
    return j - 1;
 
230
  }
 
231
 
 
232
  // this procedure performs a decryption mixing round
 
233
  static long rc2_dec_mix (t_word* r, const t_word* ekey, const long j) {
 
234
    // mix up: 3
 
235
    long result = rc2_dec_mix_up (r, ekey, j, 3);
 
236
    // mix up: 2
 
237
    result = rc2_dec_mix_up (r, ekey, result, 2);
 
238
    // mix up: 1
 
239
    result = rc2_dec_mix_up (r, ekey, result, 1);
 
240
    // mix up: 0
 
241
    result = rc2_dec_mix_up (r, ekey, result, 0);
 
242
    // here it is
 
243
    return result;
 
244
  }
 
245
 
 
246
  // this procedure do a decryption mash up
 
247
  static void rc2_dec_mash_up (t_word* r, const t_word* ekey, const long i) {
 
248
    // compute index
 
249
    long i1 = i - 1;
 
250
    if (i1 < 0) i1 += 4;
 
251
    // compute mash up
 
252
    r[i] = r[i] - ekey[r[i1] & 63];
 
253
  }
 
254
 
 
255
  // this procedure performs a decryption mash round
 
256
  static void rc2_dec_mash (t_word* r, const t_word* ekey) {
 
257
    rc2_dec_mash_up (r, ekey, 3);
 
258
    rc2_dec_mash_up (r, ekey, 2);
 
259
    rc2_dec_mash_up (r, ekey, 1);
 
260
    rc2_dec_mash_up (r, ekey, 0);
 
261
  }
 
262
 
 
263
  // this procedure perform an decryption round
 
264
  static void rc2_dec (t_word* r, const t_word* ekey) {
 
265
    // 0: initialize index
 
266
    long j = 63;
 
267
    // 1: five mixing round
 
268
    j = rc2_dec_mix (r, ekey, j);
 
269
    j = rc2_dec_mix (r, ekey, j);
 
270
    j = rc2_dec_mix (r, ekey, j);
 
271
    j = rc2_dec_mix (r, ekey, j);
 
272
    j = rc2_dec_mix (r, ekey, j);
 
273
    // 2: one mashing round
 
274
    rc2_dec_mash (r, ekey);
 
275
    // 3: six mixing round
 
276
    j = rc2_dec_mix (r, ekey, j);
 
277
    j = rc2_dec_mix (r, ekey, j);
 
278
    j = rc2_dec_mix (r, ekey, j);
 
279
    j = rc2_dec_mix (r, ekey, j);
 
280
    j = rc2_dec_mix (r, ekey, j);
 
281
    j = rc2_dec_mix (r, ekey, j);
 
282
    // 4: one mashing round
 
283
    rc2_dec_mash (r, ekey);
 
284
    // 5: five mixing rounds
 
285
    j = rc2_dec_mix (r, ekey, j);
 
286
    j = rc2_dec_mix (r, ekey, j);
 
287
    j = rc2_dec_mix (r, ekey, j);
 
288
    j = rc2_dec_mix (r, ekey, j);
 
289
    j = rc2_dec_mix (r, ekey, j);
 
290
    // basic verififcation
 
291
    if (j != -1) {
 
292
      throw Exception ("internal-error", "invalid rc2 round index");
 
293
    }
 
294
  }
 
295
 
 
296
  // -------------------------------------------------------------------------
 
297
  // - class section                                                         -
 
298
  // -------------------------------------------------------------------------
 
299
 
 
300
  // create a cipher by key
 
301
 
 
302
  Rc2::Rc2 (const Key& key) : BlockCipher (RC2_ALGO_NAME, RC2_BLOK_SIZE) {
 
303
    // initialize the effective key length
 
304
    d_klen = RC2_EKEY_BITS;
 
305
    // initialize the cipher
 
306
    p_rkey = new t_word[RC2_EKEY_WLEN];
 
307
    // set the key
 
308
    setkey (key);
 
309
  }
 
310
 
 
311
  // create a cipher by key and flag
 
312
 
 
313
  Rc2::Rc2 (const Key& key, 
 
314
            const bool rflg) : BlockCipher (RC2_ALGO_NAME, RC2_BLOK_SIZE) {
 
315
    // initialize the effective key length
 
316
    d_klen = RC2_EKEY_BITS;
 
317
    // initialize the cipher
 
318
    p_rkey = new t_word[RC2_EKEY_WLEN];
 
319
    // set the key
 
320
    setkey (key);
 
321
    // set the reverse flag
 
322
    setrflg (rflg);
 
323
  }
 
324
 
 
325
  // destroy this cipher
 
326
 
 
327
  Rc2::~Rc2 (void) {
 
328
    delete [] p_rkey;
 
329
  }
 
330
  
 
331
  // return the class name
 
332
 
 
333
  String Rc2::repr (void) const {
 
334
    return "Rc2";
 
335
  }
 
336
 
 
337
  // reset this cipher
 
338
  
 
339
  void Rc2::reset (void) {
 
340
    wrlock ();
 
341
    try {
 
342
      // reset the block cipher
 
343
      BlockCipher::reset ();
 
344
      // round key reset
 
345
      for (long i = 0; i < RC2_EKEY_WLEN; i++) {
 
346
        p_rkey[i] = 0x0000;
 
347
      }
 
348
      // expand the key
 
349
      rc2_key_expand (p_rkey, d_ckey, d_klen);
 
350
      unlock ();
 
351
    } catch (...) {
 
352
      unlock ();
 
353
      throw;
 
354
    }
 
355
  }
 
356
  
 
357
  // set the effective key length
 
358
 
 
359
  void Rc2::setklen (const long klen) {
 
360
    wrlock ();
 
361
    try {
 
362
      if ((klen <= 0) || (klen > RC2_EKEY_BITS)) {
 
363
        unlock ();
 
364
        throw Exception ("key-error", "invalid effective key size");
 
365
      }
 
366
      // set the key and reset
 
367
      d_klen = klen;
 
368
      reset  ();
 
369
      // unlock and return
 
370
      unlock ();
 
371
    } catch (...) {
 
372
      unlock ();
 
373
      throw;
 
374
    }
 
375
  }
 
376
 
 
377
  // get the effective key length
 
378
 
 
379
  long Rc2::getklen (void) const {
 
380
    rdlock ();
 
381
    try {
 
382
      long result = d_klen;
 
383
      unlock ();
 
384
      return result;
 
385
    } catch (...) {
 
386
      unlock ();
 
387
      throw;
 
388
    }
 
389
  }
 
390
 
 
391
  // encode a block buffer into another one
 
392
 
 
393
  void Rc2::encode (t_byte* bo, const t_byte* bi) {
 
394
    wrlock ();
 
395
    try {
 
396
      // bind the round state
 
397
      t_word r[RC2_WORD_SIZE] = {0x0000, 0x0000, 0x0000, 0x0000};
 
398
      rc2_bi_to_r (r, bi);
 
399
      // encode the state round
 
400
      rc2_enc (r, p_rkey);
 
401
      // bind the output buffer
 
402
      rc2_r_to_bo (bo, r);
 
403
      unlock ();
 
404
    } catch (...) {
 
405
      unlock ();
 
406
      throw;
 
407
    }
 
408
  }
 
409
 
 
410
  // decode a block buffer into another one
 
411
 
 
412
  void Rc2::decode (t_byte* bo, const t_byte* bi) {
 
413
    wrlock ();
 
414
    try {
 
415
      // bind the round state
 
416
      t_word r[RC2_WORD_SIZE] = {0x0000, 0x0000, 0x0000, 0x0000};
 
417
      rc2_bi_to_r (r, bi);
 
418
      // decode the state round
 
419
      rc2_dec (r, p_rkey);
 
420
      // bind the output buffer
 
421
      rc2_r_to_bo (bo, r);
 
422
      unlock ();
 
423
    } catch (...) {
 
424
      unlock ();
 
425
      throw;
 
426
    }
 
427
  }
 
428
 
 
429
  // -------------------------------------------------------------------------
 
430
  // - object setion                                                         -
 
431
  // -------------------------------------------------------------------------
 
432
 
 
433
  // the quark zone
 
434
  static const long QUARK_ZONE_LENGTH = 2;
 
435
  static QuarkZone  zone (QUARK_ZONE_LENGTH);
 
436
 
 
437
  // the object supported quarks
 
438
  static const long QUARK_SETKLEN = zone.intern ("set-effective-key");
 
439
  static const long QUARK_GETKLEN = zone.intern ("get-effective-key");
 
440
 
 
441
  // create a new object in a generic way
 
442
  
 
443
  Object* Rc2::mknew (Vector* argv) {
 
444
    long argc = (argv == nilp) ? 0 : argv->length ();
 
445
    // check for 1 argument
 
446
    if (argc == 1) {
 
447
      // check for a key
 
448
      Object* obj = argv->get (0);
 
449
      Key*    key = dynamic_cast <Key*> (obj);
 
450
      if (key != nilp) return new Rc2 (*key);
 
451
      throw Exception ("argument-error", "invalid arguments with RC2");
 
452
    }
 
453
    // check for 2 arguments
 
454
    if (argc == 2) {
 
455
      // check for a key
 
456
      Object* obj = argv->get (0);
 
457
      Key*    key  = dynamic_cast <Key*> (obj);
 
458
      if (key == nilp) {
 
459
        throw Exception ("argument-error", "invalid arguments with RC2");
 
460
      }
 
461
      // get the reverse flag and object
 
462
      bool rflg = argv->getbool (1);
 
463
      return new Rc2 (*key, rflg);
 
464
    }
 
465
    throw Exception ("argument-error", "too many arguments with RC2");
 
466
  }
 
467
 
 
468
  // return true if the given quark is defined
 
469
 
 
470
  bool Rc2::isquark (const long quark, const bool hflg) const {
 
471
    rdlock ();
 
472
    if (zone.exists (quark) == true) {
 
473
      unlock ();
 
474
      return true;
 
475
    }
 
476
    bool result = hflg ? BlockCipher::isquark (quark, hflg) : false;
 
477
    unlock ();
 
478
    return result;
 
479
  }
 
480
 
 
481
  // apply this object with a set of arguments and a quark
 
482
  
 
483
  Object* Rc2::apply (Runnable* robj, Nameset* nset, const long quark,
 
484
                      Vector* argv) {
 
485
    // get the number of arguments
 
486
    long argc = (argv == nilp) ? 0 : argv->length ();
 
487
    
 
488
    // check for 0 argument
 
489
    if (argc == 0) {
 
490
      if (quark == QUARK_GETKLEN) return new Integer (getklen ());
 
491
    }
 
492
    // check for 1 argument
 
493
    if (argc == 1) {
 
494
      if (quark == QUARK_SETKLEN) {
 
495
        long klen = argv->getlong (0);
 
496
        setklen (klen);
 
497
        return nilp;
 
498
      }
 
499
    }
 
500
    // call the block cipher method
 
501
    return BlockCipher::apply (robj, nset, quark, argv);
 
502
  }
 
503
}