1/*
2 * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
3 *
4 * The contents of this file constitute Original Code as defined in and are
5 * subject to the Apple Public Source License Version 1.2 (the 'License').
6 * You may not use this file except in compliance with the License. Please obtain
7 * a copy of the License at http://www.apple.com/publicsource and read it before
8 * using this file.
9 *
10 * This Original Code and all software distributed under the License are
11 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS
12 * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT
13 * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14 * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the
15 * specific language governing rights and limitations under the License.
16 */
17
18
19//
20// csputilities - utility classes for CSP implementation
21//
22#include <security_cdsa_plugin/CSPsession.h>
23#include <security_cdsa_plugin/cssmplugin.h>
24#include <security_utilities/memutils.h>
25#include <security_cdsa_utilities/cssmdates.h>
26
27using LowLevelMemoryUtilities::increment;
28
29
30//
31// Writer objects
32//
33CSPFullPluginSession::Writer::Writer(CssmData *v, uint32 n, CssmData *rem)
34: vec(v), firstVec(v), lastVec(v + n - 1), remData(rem)
35{
36    if (vec == NULL || n == 0)
37        CssmError::throwMe(CSSMERR_CSP_INVALID_OUTPUT_VECTOR);	// CDSA p.253, amended
38	useData(vec);
39    written = 0;
40}
41
42void CSPFullPluginSession::Writer::allocate(size_t needed, Allocator &alloc)
43{
44	if (!needed)
45		return; // No output buffer space needed so we're done.
46    else if (vec == firstVec && !*vec) {	// initial null vector element, wants allocation there
47        *vec = makeBuffer(needed, alloc);
48        lastVec = vec;		// ignore all subsequent buffers in vector
49		useData(vec);
50    } else {
51        // how much output space do we have left?
52        size_t size = currentSize;
53        for (CssmData *v = vec + 1; v <= lastVec; v++)
54            size += v->length();
55        if (size >= needed)
56            return;	// we're fine
57        if (remData) {
58            if (!*remData) {	        // have overflow, can allocate
59                *remData = makeBuffer(needed - size, alloc);
60                return;	// got it
61            }
62            if (size + remData->length() >= needed)
63                return;	// will fit into overflow
64        }
65        // not enough buffer space, and can't allocate
66        CssmError::throwMe(CSSMERR_CSP_OUTPUT_LENGTH_ERROR);
67    }
68}
69
70void CSPFullPluginSession::Writer::nextBlock(void * &ptr, size_t &size)
71{
72    ptr = currentBuffer;
73    size = currentSize;
74}
75
76void CSPFullPluginSession::Writer::use(size_t used)
77{
78    assert(used <= currentSize);
79    written += used;
80    if (used < currentSize) {
81        currentBuffer = increment(currentBuffer, used);
82        currentSize -= used;
83    } else {
84        if (vec < lastVec) {
85            useData(vec++);				// use next vector buffer
86        } else if (vec == lastVec && remData) {
87            useData(remData);			// use remainder buffer
88            vec++;						// mark used
89#if !defined(NDEBUG) && 0
90        } else if (vec == lastVec) {
91            vec++;
92        } else if (vec > lastVec) {
93            assert(false);				// 2nd try to overflow end
94#endif /* !NDEBUG */
95        } else {
96            currentBuffer = NULL;		// no more output buffer
97            currentSize = 0;
98        }
99    }
100}
101
102void CSPFullPluginSession::Writer::put(void *addr, size_t size)
103{
104    while (size > 0) {
105        void *p; size_t sz;
106        nextBlock(p, sz);
107        if (size < sz)
108            sz = size;	// cap transfer
109        memcpy(p, addr, sz);
110        use(sz);
111        addr = increment(addr, sz);
112        size -= sz;
113    }
114}
115
116size_t CSPFullPluginSession::Writer::close()
117{
118    return written;
119}
120
121
122//
123// Common algorithm utilities
124//
125void CSPFullPluginSession::setKey(CssmKey &key,
126								  const Context &context, CSSM_KEYCLASS keyClass,
127								  CSSM_KEYATTR_FLAGS attrs, CSSM_KEYUSE use)
128{
129    // general setup
130    memset(&key.KeyHeader, 0, sizeof(key.KeyHeader));
131    key.KeyHeader.HeaderVersion = CSSM_KEYHEADER_VERSION;
132    key.KeyHeader.CspId = plugin.myGuid();
133    key.KeyHeader.AlgorithmId = context.algorithm();
134    key.KeyHeader.KeyClass = keyClass;
135    key.KeyHeader.KeyUsage = use;
136    key.KeyHeader.KeyAttr = attrs;
137
138	CssmDate *theDate = context.get<CssmDate>(CSSM_ATTRIBUTE_START_DATE);
139	if(theDate) {
140		key.KeyHeader.StartDate = *theDate;
141	}
142	theDate = context.get<CssmDate>(CSSM_ATTRIBUTE_END_DATE);
143	if(theDate) {
144		key.KeyHeader.EndDate = *theDate;
145	}
146
147    // defaults (change as needed)
148    key.KeyHeader.WrapAlgorithmId = CSSM_ALGID_NONE;
149
150    // clear key data (standard says, "Always allocate this, ignore prior contents.")
151    key = CssmData();
152}
153