Return to padlock_rng.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / strongswan / src / libstrongswan / plugins / padlock |
1.1 misho 1: /* 2: * Copyright (C) 2008 Martin Willi 3: * HSR Hochschule fuer Technik Rapperswil 4: * 5: * This program is free software; you can redistribute it and/or modify it 6: * under the terms of the GNU General Public License as published by the 7: * Free Software Foundation; either version 2 of the License, or (at your 8: * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. 9: * 10: * This program is distributed in the hope that it will be useful, but 11: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 12: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 13: * for more details. 14: */ 15: 16: #include "padlock_rng.h" 17: 18: typedef struct private_padlock_rng_t private_padlock_rng_t; 19: typedef enum padlock_quality_factor_t padlock_quality_factor_t; 20: 21: /** 22: * Padlock RNG quality factors 23: */ 24: enum padlock_quality_factor_t { 25: /* Lowest quality: Reads 8 bytes */ 26: PADLOCK_QF0 = 0x00, 27: /* Medium quality: Reads 4 bytes */ 28: PADLOCK_QF1 = 0x01, 29: /* Better quality: Reads 2 bytes */ 30: PADLOCK_QF2 = 0x10, 31: /* Highest quality: Reads 1 byte */ 32: PADLOCK_QF3 = 0x11, 33: }; 34: 35: /** 36: * Private data of an padlock_rng_t object. 37: */ 38: struct private_padlock_rng_t { 39: 40: /** 41: * Public padlock_rng_t interface. 42: */ 43: padlock_rng_t public; 44: 45: /** 46: * Padlock quality factor 47: */ 48: padlock_quality_factor_t quality; 49: }; 50: 51: /** 52: * Get bytes from Padlock RNG. buf should have space for (len + 7) 53: */ 54: static void rng(char *buf, int len, int quality) 55: { 56: while (len > 0) 57: { 58: int status; 59: 60: /* run XSTORE until we have all bytes needed. We do not use REP, as 61: * this should not be performance critical and it's easier this way. */ 62: asm volatile ( 63: ".byte 0x0F,0xA7,0xC0 \n\t" 64: : "=D"(buf), "=a"(status) 65: : "d"(quality), "D"(buf)); 66: 67: /* bits[0..4] of status word contains the number of bytes read */ 68: len -= status & 0x1F; 69: } 70: } 71: 72: METHOD(rng_t, allocate_bytes, bool, 73: private_padlock_rng_t *this, size_t bytes, chunk_t *chunk) 74: { 75: chunk->len = bytes; 76: /* padlock requires some additional bytes */ 77: chunk->ptr = malloc(bytes + 7); 78: 79: rng(chunk->ptr, chunk->len, this->quality); 80: return TRUE; 81: } 82: 83: METHOD(rng_t, get_bytes, bool, 84: private_padlock_rng_t *this, size_t bytes, uint8_t *buffer) 85: { 86: chunk_t chunk; 87: 88: /* Padlock needs a larger buffer than "bytes", we need a new buffer */ 89: allocate_bytes(this, bytes, &chunk); 90: memcpy(buffer, chunk.ptr, bytes); 91: chunk_clear(&chunk); 92: return TRUE; 93: } 94: 95: METHOD(rng_t, destroy, void, 96: private_padlock_rng_t *this) 97: { 98: free(this); 99: } 100: 101: /* 102: * Described in header. 103: */ 104: padlock_rng_t *padlock_rng_create(rng_quality_t quality) 105: { 106: private_padlock_rng_t *this; 107: 108: INIT(this, 109: .public = { 110: .rng = { 111: .get_bytes = _get_bytes, 112: .allocate_bytes = _allocate_bytes, 113: .destroy = _destroy, 114: }, 115: }, 116: ); 117: 118: /* map RNG quality to Padlock quality factor */ 119: switch (quality) 120: { 121: case RNG_WEAK: 122: this->quality = PADLOCK_QF0; 123: break; 124: case RNG_STRONG: 125: this->quality = PADLOCK_QF1; 126: break; 127: case RNG_TRUE: 128: this->quality = PADLOCK_QF3; 129: break; 130: default: 131: free(this); 132: return NULL; 133: } 134: return &this->public; 135: } 136: